[WIN32K] Realize PTEXTOBJ in FontGetObject if it was not initialized
[reactos.git] / win32ss / gdi / ntgdi / font.c
1 /*
2 * PROJECT: ReactOS win32 kernel mode subsystem
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: win32ss/gdi/ntgdi/font.c
5 * PURPOSE: Font
6 * PROGRAMMERS: James Tabor <james.tabor@reactos.org>
7 * Timo Kreuzer <timo.kreuzer@reactos.org>
8 * Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
9 */
10
11 /** Includes ******************************************************************/
12
13 #include <win32k.h>
14
15 #define NDEBUG
16 #include <debug.h>
17
18 HFONT APIENTRY HfontCreate( IN PENUMLOGFONTEXDVW pelfw,IN ULONG cjElfw,IN LFTYPE lft,IN FLONG fl,IN PVOID pvCliData );
19
20 /** Internal ******************************************************************/
21
22 HFONT FASTCALL
23 GreCreateFontIndirectW( LOGFONTW *lplf )
24 {
25 if (lplf)
26 {
27 ENUMLOGFONTEXDVW Logfont;
28
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));
36
37 Logfont.elfDesignVector.dvNumAxes = 0;
38
39 RtlZeroMemory( &Logfont.elfDesignVector, sizeof(DESIGNVECTOR));
40
41 return HfontCreate((PENUMLOGFONTEXDVW)&Logfont, 0, 0, 0, NULL );
42 }
43 else return NULL;
44 }
45
46 DWORD
47 FASTCALL
48 GreGetKerningPairs(
49 HDC hDC,
50 ULONG NumPairs,
51 LPKERNINGPAIR krnpair)
52 {
53 PDC dc;
54 PDC_ATTR pdcattr;
55 PTEXTOBJ TextObj;
56 PFONTGDI FontGDI;
57 DWORD Count;
58 KERNINGPAIR *pKP;
59
60 dc = DC_LockDc(hDC);
61 if (!dc)
62 {
63 EngSetLastError(ERROR_INVALID_HANDLE);
64 return 0;
65 }
66
67 pdcattr = dc->pdcattr;
68 TextObj = RealizeFontInit(pdcattr->hlfntNew);
69 DC_UnlockDc(dc);
70
71 if (!TextObj)
72 {
73 EngSetLastError(ERROR_INVALID_HANDLE);
74 return 0;
75 }
76
77 FontGDI = ObjToGDI(TextObj->Font, FONT);
78 TEXTOBJ_UnlockText(TextObj);
79
80 Count = ftGdiGetKerningPairs(FontGDI,0,NULL);
81
82 if ( Count && krnpair )
83 {
84 if (Count > NumPairs)
85 {
86 EngSetLastError(ERROR_INSUFFICIENT_BUFFER);
87 return 0;
88 }
89 pKP = ExAllocatePoolWithTag(PagedPool, Count * sizeof(KERNINGPAIR), GDITAG_TEXT);
90 if (!pKP)
91 {
92 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
93 return 0;
94 }
95 ftGdiGetKerningPairs(FontGDI,Count,pKP);
96
97 RtlCopyMemory(krnpair, pKP, Count * sizeof(KERNINGPAIR));
98
99 ExFreePoolWithTag(pKP,GDITAG_TEXT);
100 }
101 return Count;
102 }
103
104 /*
105
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
110 value.
111
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
114 for GCPCLASS_LATIN!
115
116 */
117 #if 0
118 DWORD
119 FASTCALL
120 GreGetCharacterPlacementW(
121 HDC hdc,
122 LPCWSTR pwsz,
123 INT nCount,
124 INT nMaxExtent,
125 LPGCP_RESULTSW pgcpw,
126 DWORD dwFlags)
127 {
128 GCP_RESULTSW gcpwSave;
129 UINT i, nSet, cSet;
130 INT *tmpDxCaretPos;
131 LONG Cx;
132 SIZE Size = {0,0};
133
134 DPRINT1("GreGCPW Start\n");
135
136 if (!pgcpw)
137 {
138 if (GreGetTextExtentW( hdc, pwsz, nCount, &Size, 1))
139 return MAKELONG(Size.cx, Size.cy);
140 return 0;
141 }
142
143 DPRINT1("GreGCPW 1\n");
144
145 RtlCopyMemory(&gcpwSave, pgcpw, sizeof(GCP_RESULTSW));
146
147 cSet = nSet = nCount;
148
149 if ( nCount > gcpwSave.nGlyphs ) cSet = gcpwSave.nGlyphs;
150
151 /* GCP_JUSTIFY may only be used in conjunction with GCP_MAXEXTENT. */
152 if ( dwFlags & GCP_JUSTIFY) dwFlags |= GCP_MAXEXTENT;
153
154 if ( !gcpwSave.lpDx && gcpwSave.lpCaretPos )
155 tmpDxCaretPos = gcpwSave.lpCaretPos;
156 else
157 tmpDxCaretPos = gcpwSave.lpDx;
158
159 if ( !GreGetTextExtentExW( hdc,
160 pwsz,
161 cSet,
162 nMaxExtent,
163 ((dwFlags & GCP_MAXEXTENT) ? (PULONG) &cSet : NULL),
164 (PULONG) tmpDxCaretPos,
165 &Size,
166 0) )
167 {
168 return 0;
169 }
170
171 DPRINT1("GreGCPW 2\n");
172
173 nSet = cSet;
174
175 if ( tmpDxCaretPos && nSet > 0)
176 {
177 for (i = (nSet - 1); i > 0; i--)
178 {
179 tmpDxCaretPos[i] -= tmpDxCaretPos[i - 1];
180 }
181 }
182
183 if ( !(dwFlags & GCP_MAXEXTENT) || nSet )
184 {
185 if ( (dwFlags & GCP_USEKERNING) &&
186 ( gcpwSave.lpDx ||
187 gcpwSave.lpCaretPos ) &&
188 nSet >= 2 )
189 {
190 DWORD Count;
191 LPKERNINGPAIR pKP;
192
193 Count = GreGetKerningPairs( hdc, 0, NULL);
194 if (Count)
195 {
196 pKP = ExAllocatePoolWithTag(PagedPool, Count * sizeof(KERNINGPAIR), GDITAG_TEXT);
197 if (pKP)
198 {
199 if ( GreGetKerningPairs( hdc, Count, pKP) != Count)
200 {
201 ExFreePoolWithTag( pKP, GDITAG_TEXT);
202 return 0;
203 }
204
205 if ( (ULONG_PTR)(pKP) < ((ULONG_PTR)(pKP) + (ULONG_PTR)(Count * sizeof(KERNINGPAIR))) )
206 {
207 DPRINT1("We Need to Do Something HERE!\n");
208 }
209
210 ExFreePoolWithTag( pKP, GDITAG_TEXT);
211
212 if ( dwFlags & GCP_MAXEXTENT )
213 {
214 if ( Size.cx > nMaxExtent )
215 {
216 for (Cx = Size.cx; nSet > 0; nSet--)
217 {
218 Cx -= tmpDxCaretPos[nSet - 1];
219 Size.cx = Cx;
220 if ( Cx <= nMaxExtent ) break;
221 }
222 }
223 if ( !nSet )
224 {
225 pgcpw->nGlyphs = 0;
226 pgcpw->nMaxFit = 0;
227 return 0;
228 }
229 }
230 }
231 }
232 }
233
234 if ( (dwFlags & GCP_JUSTIFY) &&
235 ( gcpwSave.lpDx ||
236 gcpwSave.lpCaretPos ) &&
237 nSet )
238 {
239 DPRINT1("We Need to Do Something HERE 2!\n");
240 }
241
242 if ( gcpwSave.lpDx && gcpwSave.lpCaretPos )
243 RtlCopyMemory( gcpwSave.lpCaretPos, gcpwSave.lpDx, nSet * sizeof(LONG));
244
245 if ( gcpwSave.lpCaretPos )
246 {
247 int pos = 0;
248 i = 0;
249 if ( nSet > 0 )
250 {
251 do
252 {
253 Cx = gcpwSave.lpCaretPos[i];
254 gcpwSave.lpCaretPos[i] = pos;
255 pos += Cx;
256 ++i;
257 }
258 while ( i < nSet );
259 }
260 }
261
262 if ( gcpwSave.lpOutString )
263 RtlCopyMemory(gcpwSave.lpOutString, pwsz, nSet * sizeof(WCHAR));
264
265 if ( gcpwSave.lpClass )
266 RtlFillMemory(gcpwSave.lpClass, nSet, GCPCLASS_LATIN);
267
268 if ( gcpwSave.lpOrder )
269 {
270 for (i = 0; i < nSet; i++)
271 gcpwSave.lpOrder[i] = i;
272 }
273
274 if ( gcpwSave.lpGlyphs )
275 {
276 if ( GreGetGlyphIndicesW( hdc, pwsz, nSet, gcpwSave.lpGlyphs, 0, 0) == GDI_ERROR )
277 {
278 nSet = 0;
279 Size.cx = 0;
280 Size.cy = 0;
281 }
282 }
283 pgcpw->nGlyphs = nSet;
284 pgcpw->nMaxFit = nSet;
285 }
286 DPRINT1("GreGCPW Exit\n");
287 return MAKELONG(Size.cx, Size.cy);
288 }
289 #endif
290
291 ULONG
292 FASTCALL
293 FontGetObject(PTEXTOBJ plfont, ULONG cjBuffer, PVOID pvBuffer)
294 {
295 ULONG cjMaxSize;
296 ENUMLOGFONTEXDVW *plf = &plfont->logfont;
297
298 if (!(plfont->fl & TEXTOBJECT_INIT))
299 {
300 NTSTATUS Status;
301 DPRINT1("FontGetObject font not initialized!\n");
302
303 Status = TextIntRealizeFont(plfont->BaseObject.hHmgr, plfont);
304 if (!NT_SUCCESS(Status))
305 {
306 DPRINT1("FontGetObject(TextIntRealizeFont) Status = 0x%lx\n", Status);
307 }
308 }
309
310 /* If buffer is NULL, only the size is requested */
311 if (pvBuffer == NULL) return sizeof(LOGFONTW);
312
313 /* Calculate the maximum size according to number of axes */
314 cjMaxSize = FIELD_OFFSET(ENUMLOGFONTEXDVW,
315 elfDesignVector.dvValues[plf->elfDesignVector.dvNumAxes]);
316
317 if (cjBuffer > cjMaxSize) cjBuffer = cjMaxSize;
318
319 RtlCopyMemory(pvBuffer, plf, cjBuffer);
320
321 return cjBuffer;
322 }
323
324 DWORD
325 FASTCALL
326 IntGetCharDimensions(HDC hdc, PTEXTMETRICW ptm, PDWORD height)
327 {
328 PDC pdc;
329 PDC_ATTR pdcattr;
330 PTEXTOBJ TextObj;
331 SIZE sz;
332 TMW_INTERNAL tmwi;
333 BOOL Good;
334
335 static const WCHAR alphabet[] = {
336 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
337 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
338 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
339
340 if(!ftGdiGetTextMetricsW(hdc, &tmwi)) return 0;
341
342 pdc = DC_LockDc(hdc);
343
344 if (!pdc) return 0;
345
346 pdcattr = pdc->pdcattr;
347
348 TextObj = RealizeFontInit(pdcattr->hlfntNew);
349 if ( !TextObj )
350 {
351 DC_UnlockDc(pdc);
352 return 0;
353 }
354 Good = TextIntGetTextExtentPoint(pdc, TextObj, alphabet, 52, 0, NULL, 0, &sz, 0);
355 TEXTOBJ_UnlockText(TextObj);
356 DC_UnlockDc(pdc);
357
358 if (!Good) return 0;
359 if (ptm) *ptm = tmwi.TextMetric;
360 if (height) *height = tmwi.TextMetric.tmHeight;
361
362 return (sz.cx / 26 + 1) / 2;
363 }
364
365
366 DWORD
367 FASTCALL
368 IntGetFontLanguageInfo(PDC Dc)
369 {
370 PDC_ATTR pdcattr;
371 FONTSIGNATURE fontsig;
372 static const DWORD GCP_DBCS_MASK=0x003F0000,
373 GCP_DIACRITIC_MASK=0x00000000,
374 FLI_GLYPHS_MASK=0x00000000,
375 GCP_GLYPHSHAPE_MASK=0x00000040,
376 GCP_KASHIDA_MASK=0x00000000,
377 GCP_LIGATE_MASK=0x00000000,
378 GCP_USEKERNING_MASK=0x00000000,
379 GCP_REORDER_MASK=0x00000060;
380
381 DWORD result=0;
382
383 ftGdiGetTextCharsetInfo( Dc, &fontsig, 0 );
384
385 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
386 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
387 result|=GCP_DBCS;
388
389 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
390 result|=GCP_DIACRITIC;
391
392 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
393 result|=FLI_GLYPHS;
394
395 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
396 result|=GCP_GLYPHSHAPE;
397
398 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
399 result|=GCP_KASHIDA;
400
401 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
402 result|=GCP_LIGATE;
403
404 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
405 result|=GCP_USEKERNING;
406
407 pdcattr = Dc->pdcattr;
408
409 /* This might need a test for a HEBREW- or ARABIC_CHARSET as well */
410 if ( pdcattr->lTextAlign & TA_RTLREADING )
411 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
412 result|=GCP_REORDER;
413
414 return result;
415 }
416
417 PTEXTOBJ
418 FASTCALL
419 RealizeFontInit(HFONT hFont)
420 {
421 NTSTATUS Status = STATUS_SUCCESS;
422 PTEXTOBJ pTextObj;
423
424 pTextObj = TEXTOBJ_LockText(hFont);
425
426 if ( pTextObj && !(pTextObj->fl & TEXTOBJECT_INIT))
427 {
428 Status = TextIntRealizeFont(hFont, pTextObj);
429 if (!NT_SUCCESS(Status))
430 {
431 TEXTOBJ_UnlockText(pTextObj);
432 return NULL;
433 }
434 }
435 return pTextObj;
436 }
437
438
439 /** Functions ******************************************************************/
440
441 INT
442 APIENTRY
443 NtGdiAddFontResourceW(
444 IN WCHAR *pwcFiles,
445 IN ULONG cwc,
446 IN ULONG cFiles,
447 IN FLONG fl,
448 IN DWORD dwPidTid,
449 IN OPTIONAL DESIGNVECTOR *pdv)
450 {
451 UNICODE_STRING SafeFileName;
452 INT Ret;
453
454 DBG_UNREFERENCED_PARAMETER(cFiles);
455 DBG_UNREFERENCED_PARAMETER(dwPidTid);
456 DBG_UNREFERENCED_PARAMETER(pdv);
457
458 DPRINT("NtGdiAddFontResourceW\n");
459
460 /* cwc = Length + trailing zero. */
461 if ((cwc <= 1) || (cwc > UNICODE_STRING_MAX_CHARS))
462 return 0;
463
464 SafeFileName.MaximumLength = (USHORT)(cwc * sizeof(WCHAR));
465 SafeFileName.Length = SafeFileName.MaximumLength - sizeof(UNICODE_NULL);
466 SafeFileName.Buffer = ExAllocatePoolWithTag(PagedPool,
467 SafeFileName.MaximumLength,
468 TAG_STRING);
469 if (!SafeFileName.Buffer)
470 {
471 return 0;
472 }
473
474 _SEH2_TRY
475 {
476 ProbeForRead(pwcFiles, cwc * sizeof(WCHAR), sizeof(WCHAR));
477 RtlCopyMemory(SafeFileName.Buffer, pwcFiles, SafeFileName.Length);
478 }
479 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
480 {
481 ExFreePoolWithTag(SafeFileName.Buffer, TAG_STRING);
482 _SEH2_YIELD(return 0);
483 }
484 _SEH2_END;
485
486 SafeFileName.Buffer[SafeFileName.Length / sizeof(WCHAR)] = UNICODE_NULL;
487 Ret = IntGdiAddFontResource(&SafeFileName, fl);
488
489 ExFreePoolWithTag(SafeFileName.Buffer, TAG_STRING);
490 return Ret;
491 }
492
493 HANDLE
494 APIENTRY
495 NtGdiAddFontMemResourceEx(
496 IN PVOID pvBuffer,
497 IN DWORD cjBuffer,
498 IN DESIGNVECTOR *pdv,
499 IN ULONG cjDV,
500 OUT DWORD *pNumFonts)
501 {
502 _SEH2_VOLATILE PVOID Buffer = NULL;
503 HANDLE Ret;
504 DWORD NumFonts = 0;
505
506 DPRINT("NtGdiAddFontMemResourceEx\n");
507 DBG_UNREFERENCED_PARAMETER(pdv);
508 DBG_UNREFERENCED_PARAMETER(cjDV);
509
510 if (!pvBuffer || !cjBuffer)
511 return NULL;
512
513 _SEH2_TRY
514 {
515 ProbeForRead(pvBuffer, cjBuffer, sizeof(BYTE));
516 Buffer = ExAllocatePoolWithQuotaTag(PagedPool, cjBuffer, TAG_FONT);
517 RtlCopyMemory(Buffer, pvBuffer, cjBuffer);
518 }
519 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
520 {
521 if (Buffer != NULL)
522 {
523 ExFreePoolWithTag(Buffer, TAG_FONT);
524 }
525 _SEH2_YIELD(return NULL);
526 }
527 _SEH2_END;
528
529 Ret = IntGdiAddFontMemResource(Buffer, cjBuffer, &NumFonts);
530 ExFreePoolWithTag(Buffer, TAG_FONT);
531
532 _SEH2_TRY
533 {
534 ProbeForWrite(pNumFonts, sizeof(NumFonts), 1);
535 *pNumFonts = NumFonts;
536 }
537 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
538 {
539 /* Leak it? */
540 _SEH2_YIELD(return NULL);
541 }
542 _SEH2_END;
543
544
545 return Ret;
546 }
547
548
549 BOOL
550 APIENTRY
551 NtGdiRemoveFontMemResourceEx(
552 IN HANDLE hMMFont)
553 {
554 return IntGdiRemoveFontMemResource(hMMFont);
555 }
556
557
558 /*
559 * @unimplemented
560 */
561 DWORD
562 APIENTRY
563 NtGdiGetCharacterPlacementW(
564 IN HDC hdc,
565 IN LPWSTR pwsz,
566 IN INT nCount,
567 IN INT nMaxExtent,
568 IN OUT LPGCP_RESULTSW pgcpw,
569 IN DWORD dwFlags)
570 {
571 UNIMPLEMENTED;
572 return 0;
573 #if 0
574 return GreGetCharacterPlacementW( hdc,
575 pwsz,
576 nCount,
577 nMaxExtent,
578 pgcpw,
579 dwFlags);
580 #endif
581 }
582
583 DWORD
584 APIENTRY
585 NtGdiGetFontData(
586 HDC hDC,
587 DWORD Table,
588 DWORD Offset,
589 LPVOID Buffer,
590 DWORD Size)
591 {
592 PDC Dc;
593 PDC_ATTR pdcattr;
594 HFONT hFont;
595 PTEXTOBJ TextObj;
596 PFONTGDI FontGdi;
597 DWORD Result = GDI_ERROR;
598 NTSTATUS Status = STATUS_SUCCESS;
599
600 if (Buffer && Size)
601 {
602 _SEH2_TRY
603 {
604 ProbeForRead(Buffer, Size, 1);
605 }
606 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
607 {
608 Status = _SEH2_GetExceptionCode();
609 }
610 _SEH2_END
611 }
612
613 if (!NT_SUCCESS(Status)) return Result;
614
615 Dc = DC_LockDc(hDC);
616 if (Dc == NULL)
617 {
618 EngSetLastError(ERROR_INVALID_HANDLE);
619 return GDI_ERROR;
620 }
621 pdcattr = Dc->pdcattr;
622
623 hFont = pdcattr->hlfntNew;
624 TextObj = RealizeFontInit(hFont);
625 DC_UnlockDc(Dc);
626
627 if (TextObj == NULL)
628 {
629 EngSetLastError(ERROR_INVALID_HANDLE);
630 return GDI_ERROR;
631 }
632
633 FontGdi = ObjToGDI(TextObj->Font, FONT);
634
635 Result = ftGdiGetFontData(FontGdi, Table, Offset, Buffer, Size);
636
637 TEXTOBJ_UnlockText(TextObj);
638
639 return Result;
640 }
641
642 /*
643 * @implemented
644 */
645 DWORD
646 APIENTRY
647 NtGdiGetFontUnicodeRanges(
648 IN HDC hdc,
649 OUT OPTIONAL LPGLYPHSET pgs)
650 {
651 PDC pDc;
652 PDC_ATTR pdcattr;
653 HFONT hFont;
654 PTEXTOBJ TextObj;
655 PFONTGDI FontGdi;
656 DWORD Size = 0;
657 PGLYPHSET pgsSafe;
658 NTSTATUS Status = STATUS_SUCCESS;
659
660 pDc = DC_LockDc(hdc);
661 if (!pDc)
662 {
663 EngSetLastError(ERROR_INVALID_HANDLE);
664 return 0;
665 }
666
667 pdcattr = pDc->pdcattr;
668
669 hFont = pdcattr->hlfntNew;
670 TextObj = RealizeFontInit(hFont);
671
672 if ( TextObj == NULL)
673 {
674 EngSetLastError(ERROR_INVALID_HANDLE);
675 goto Exit;
676 }
677 FontGdi = ObjToGDI(TextObj->Font, FONT);
678
679 Size = ftGetFontUnicodeRanges( FontGdi, NULL);
680
681 if (Size && pgs)
682 {
683 pgsSafe = ExAllocatePoolWithTag(PagedPool, Size, GDITAG_TEXT);
684 if (!pgsSafe)
685 {
686 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
687 Size = 0;
688 goto Exit;
689 }
690
691 Size = ftGetFontUnicodeRanges( FontGdi, pgsSafe);
692
693 if (Size)
694 {
695 _SEH2_TRY
696 {
697 ProbeForWrite(pgs, Size, 1);
698 RtlCopyMemory(pgs, pgsSafe, Size);
699 }
700 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
701 {
702 Status = _SEH2_GetExceptionCode();
703 }
704 _SEH2_END
705
706 if (!NT_SUCCESS(Status)) Size = 0;
707 }
708 ExFreePoolWithTag(pgsSafe, GDITAG_TEXT);
709 }
710 Exit:
711 TEXTOBJ_UnlockText(TextObj);
712 DC_UnlockDc(pDc);
713 return Size;
714 }
715
716 ULONG
717 APIENTRY
718 NtGdiGetGlyphOutline(
719 IN HDC hdc,
720 IN WCHAR wch,
721 IN UINT iFormat,
722 OUT LPGLYPHMETRICS pgm,
723 IN ULONG cjBuf,
724 OUT OPTIONAL PVOID UnsafeBuf,
725 IN LPMAT2 pmat2,
726 IN BOOL bIgnoreRotation)
727 {
728 ULONG Ret = GDI_ERROR;
729 PDC dc;
730 PVOID pvBuf = NULL;
731 GLYPHMETRICS gm;
732 NTSTATUS Status = STATUS_SUCCESS;
733
734 dc = DC_LockDc(hdc);
735 if (!dc)
736 {
737 EngSetLastError(ERROR_INVALID_HANDLE);
738 return GDI_ERROR;
739 }
740
741 if (UnsafeBuf && cjBuf)
742 {
743 pvBuf = ExAllocatePoolWithTag(PagedPool, cjBuf, GDITAG_TEXT);
744 if (!pvBuf)
745 {
746 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
747 goto Exit;
748 }
749 }
750
751 Ret = ftGdiGetGlyphOutline( dc,
752 wch,
753 iFormat,
754 pgm ? &gm : NULL,
755 cjBuf,
756 pvBuf,
757 pmat2,
758 bIgnoreRotation);
759
760 if (pvBuf)
761 {
762 _SEH2_TRY
763 {
764 ProbeForWrite(UnsafeBuf, cjBuf, 1);
765 RtlCopyMemory(UnsafeBuf, pvBuf, cjBuf);
766 }
767 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
768 {
769 Status = _SEH2_GetExceptionCode();
770 }
771 _SEH2_END
772
773 ExFreePoolWithTag(pvBuf, GDITAG_TEXT);
774 }
775
776 if (pgm)
777 {
778 _SEH2_TRY
779 {
780 ProbeForWrite(pgm, sizeof(GLYPHMETRICS), 1);
781 RtlCopyMemory(pgm, &gm, sizeof(GLYPHMETRICS));
782 }
783 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
784 {
785 Status = _SEH2_GetExceptionCode();
786 }
787 _SEH2_END
788 }
789
790 if (! NT_SUCCESS(Status))
791 {
792 EngSetLastError(ERROR_INVALID_PARAMETER);
793 Ret = GDI_ERROR;
794 }
795
796 Exit:
797 DC_UnlockDc(dc);
798 return Ret;
799 }
800
801 DWORD
802 APIENTRY
803 NtGdiGetKerningPairs(HDC hDC,
804 ULONG NumPairs,
805 LPKERNINGPAIR krnpair)
806 {
807 PDC dc;
808 PDC_ATTR pdcattr;
809 PTEXTOBJ TextObj;
810 PFONTGDI FontGDI;
811 DWORD Count;
812 KERNINGPAIR *pKP;
813 NTSTATUS Status = STATUS_SUCCESS;
814
815 dc = DC_LockDc(hDC);
816 if (!dc)
817 {
818 EngSetLastError(ERROR_INVALID_HANDLE);
819 return 0;
820 }
821
822 pdcattr = dc->pdcattr;
823 TextObj = RealizeFontInit(pdcattr->hlfntNew);
824 DC_UnlockDc(dc);
825
826 if (!TextObj)
827 {
828 EngSetLastError(ERROR_INVALID_HANDLE);
829 return 0;
830 }
831
832 FontGDI = ObjToGDI(TextObj->Font, FONT);
833 TEXTOBJ_UnlockText(TextObj);
834
835 Count = ftGdiGetKerningPairs(FontGDI,0,NULL);
836
837 if ( Count && krnpair )
838 {
839 if (Count > NumPairs)
840 {
841 EngSetLastError(ERROR_INSUFFICIENT_BUFFER);
842 return 0;
843 }
844 pKP = ExAllocatePoolWithTag(PagedPool, Count * sizeof(KERNINGPAIR), GDITAG_TEXT);
845 if (!pKP)
846 {
847 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
848 return 0;
849 }
850 ftGdiGetKerningPairs(FontGDI,Count,pKP);
851 _SEH2_TRY
852 {
853 ProbeForWrite(krnpair, Count * sizeof(KERNINGPAIR), 1);
854 RtlCopyMemory(krnpair, pKP, Count * sizeof(KERNINGPAIR));
855 }
856 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
857 {
858 Status = _SEH2_GetExceptionCode();
859 }
860 _SEH2_END
861 if (!NT_SUCCESS(Status))
862 {
863 EngSetLastError(ERROR_INVALID_PARAMETER);
864 Count = 0;
865 }
866 ExFreePoolWithTag(pKP,GDITAG_TEXT);
867 }
868 return Count;
869 }
870
871 /*
872 From "Undocumented Windows 2000 Secrets" Appendix B, Table B-2, page
873 472, this is NtGdiGetOutlineTextMetricsInternalW.
874 */
875 ULONG
876 APIENTRY
877 NtGdiGetOutlineTextMetricsInternalW (HDC hDC,
878 ULONG Data,
879 OUTLINETEXTMETRICW *otm,
880 TMDIFF *Tmd)
881 {
882 PDC dc;
883 PDC_ATTR pdcattr;
884 PTEXTOBJ TextObj;
885 PFONTGDI FontGDI;
886 HFONT hFont = 0;
887 ULONG Size;
888 OUTLINETEXTMETRICW *potm;
889 NTSTATUS Status = STATUS_SUCCESS;
890
891 dc = DC_LockDc(hDC);
892 if (!dc)
893 {
894 EngSetLastError(ERROR_INVALID_HANDLE);
895 return 0;
896 }
897 pdcattr = dc->pdcattr;
898 hFont = pdcattr->hlfntNew;
899 TextObj = RealizeFontInit(hFont);
900 DC_UnlockDc(dc);
901 if (!TextObj)
902 {
903 EngSetLastError(ERROR_INVALID_HANDLE);
904 return 0;
905 }
906 FontGDI = ObjToGDI(TextObj->Font, FONT);
907 TextIntUpdateSize(dc, TextObj, FontGDI, TRUE);
908 TEXTOBJ_UnlockText(TextObj);
909 Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
910 if (!otm) return Size;
911 if (Size > Data)
912 {
913 EngSetLastError(ERROR_INSUFFICIENT_BUFFER);
914 return 0;
915 }
916 potm = ExAllocatePoolWithTag(PagedPool, Size, GDITAG_TEXT);
917 if (!potm)
918 {
919 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
920 return 0;
921 }
922 IntGetOutlineTextMetrics(FontGDI, Size, potm);
923 if (otm)
924 {
925 _SEH2_TRY
926 {
927 ProbeForWrite(otm, Size, 1);
928 RtlCopyMemory(otm, potm, Size);
929 }
930 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
931 {
932 Status = _SEH2_GetExceptionCode();
933 }
934 _SEH2_END
935
936 if (!NT_SUCCESS(Status))
937 {
938 EngSetLastError(ERROR_INVALID_PARAMETER);
939 Size = 0;
940 }
941 }
942 ExFreePoolWithTag(potm,GDITAG_TEXT);
943 return Size;
944 }
945
946 W32KAPI
947 BOOL
948 APIENTRY
949 NtGdiGetFontResourceInfoInternalW(
950 IN LPWSTR pwszFiles,
951 IN ULONG cwc,
952 IN ULONG cFiles,
953 IN UINT cjIn,
954 IN OUT LPDWORD pdwBytes,
955 OUT LPVOID pvBuf,
956 IN DWORD dwType)
957 {
958 NTSTATUS Status = STATUS_SUCCESS;
959 DWORD dwBytes, dwBytesRequested;
960 UNICODE_STRING SafeFileNames;
961 BOOL bRet = FALSE;
962 ULONG cbStringSize;
963 LPVOID Buffer;
964
965 /* FIXME: Handle cFiles > 0 */
966
967 /* Check for valid dwType values */
968 if (dwType > 5)
969 {
970 EngSetLastError(ERROR_INVALID_PARAMETER);
971 return FALSE;
972 }
973
974 /* Allocate a safe unicode string buffer */
975 cbStringSize = cwc * sizeof(WCHAR);
976 SafeFileNames.MaximumLength = SafeFileNames.Length = (USHORT)cbStringSize - sizeof(WCHAR);
977 SafeFileNames.Buffer = ExAllocatePoolWithTag(PagedPool,
978 cbStringSize,
979 TAG_USTR);
980 if (!SafeFileNames.Buffer)
981 {
982 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
983 return FALSE;
984 }
985 RtlZeroMemory(SafeFileNames.Buffer, SafeFileNames.MaximumLength);
986
987 /* Check buffers and copy pwszFiles to safe unicode string */
988 _SEH2_TRY
989 {
990 ProbeForRead(pwszFiles, cbStringSize, 1);
991 ProbeForWrite(pdwBytes, sizeof(DWORD), 1);
992 if (pvBuf)
993 ProbeForWrite(pvBuf, cjIn, 1);
994
995 dwBytes = *pdwBytes;
996 dwBytesRequested = dwBytes;
997
998 RtlCopyMemory(SafeFileNames.Buffer, pwszFiles, cbStringSize);
999 if (dwBytes > 0)
1000 {
1001 Buffer = ExAllocatePoolWithTag(PagedPool, dwBytes, TAG_FINF);
1002 }
1003 else
1004 {
1005 Buffer = ExAllocatePoolWithTag(PagedPool, sizeof(DWORD), TAG_FINF);
1006 }
1007 }
1008 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1009 {
1010 Status = _SEH2_GetExceptionCode();
1011 }
1012 _SEH2_END
1013
1014 if(!NT_SUCCESS(Status))
1015 {
1016 SetLastNtError(Status);
1017 /* Free the string buffer for the safe filename */
1018 ExFreePoolWithTag(SafeFileNames.Buffer, TAG_USTR);
1019 return FALSE;
1020 }
1021
1022 /* Do the actual call */
1023 bRet = IntGdiGetFontResourceInfo(&SafeFileNames,
1024 (pvBuf ? Buffer : NULL),
1025 &dwBytes, dwType);
1026
1027 /* Check if succeeded */
1028 if (bRet)
1029 {
1030 /* Copy the data back to caller */
1031 _SEH2_TRY
1032 {
1033 /* Buffers are already probed */
1034 if (pvBuf && dwBytesRequested > 0)
1035 RtlCopyMemory(pvBuf, Buffer, min(dwBytesRequested, dwBytes));
1036 *pdwBytes = dwBytes;
1037 }
1038 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1039 {
1040 Status = _SEH2_GetExceptionCode();
1041 }
1042 _SEH2_END
1043
1044 if(!NT_SUCCESS(Status))
1045 {
1046 SetLastNtError(Status);
1047 bRet = FALSE;
1048 }
1049 }
1050
1051 ExFreePoolWithTag(Buffer, TAG_FINF);
1052 /* Free the string for the safe filenames */
1053 ExFreePoolWithTag(SafeFileNames.Buffer, TAG_USTR);
1054
1055 return bRet;
1056 }
1057
1058 /*
1059 * @unimplemented
1060 */
1061 BOOL
1062 APIENTRY
1063 NtGdiGetRealizationInfo(
1064 IN HDC hdc,
1065 OUT PREALIZATION_INFO pri,
1066 IN HFONT hf)
1067 {
1068 PDC pDc;
1069 PTEXTOBJ pTextObj;
1070 PFONTGDI pFontGdi;
1071 PDC_ATTR pdcattr;
1072 BOOL Ret = FALSE;
1073 INT i = 0;
1074 REALIZATION_INFO ri;
1075
1076 pDc = DC_LockDc(hdc);
1077 if (!pDc)
1078 {
1079 EngSetLastError(ERROR_INVALID_HANDLE);
1080 return 0;
1081 }
1082 pdcattr = pDc->pdcattr;
1083 pTextObj = RealizeFontInit(pdcattr->hlfntNew);
1084 pFontGdi = ObjToGDI(pTextObj->Font, FONT);
1085 TEXTOBJ_UnlockText(pTextObj);
1086 DC_UnlockDc(pDc);
1087
1088 Ret = ftGdiRealizationInfo(pFontGdi, &ri);
1089 if (Ret)
1090 {
1091 if (pri)
1092 {
1093 NTSTATUS Status = STATUS_SUCCESS;
1094 _SEH2_TRY
1095 {
1096 ProbeForWrite(pri, sizeof(REALIZATION_INFO), 1);
1097 RtlCopyMemory(pri, &ri, sizeof(REALIZATION_INFO));
1098 }
1099 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1100 {
1101 Status = _SEH2_GetExceptionCode();
1102 }
1103 _SEH2_END
1104
1105 if(!NT_SUCCESS(Status))
1106 {
1107 SetLastNtError(Status);
1108 return FALSE;
1109 }
1110 }
1111 do
1112 {
1113 if (GdiHandleTable->cfPublic[i].hf == hf)
1114 {
1115 GdiHandleTable->cfPublic[i].iTechnology = ri.iTechnology;
1116 GdiHandleTable->cfPublic[i].iUniq = ri.iUniq;
1117 GdiHandleTable->cfPublic[i].dwUnknown = ri.dwUnknown;
1118 GdiHandleTable->cfPublic[i].dwCFCount = GdiHandleTable->dwCFCount;
1119 GdiHandleTable->cfPublic[i].fl |= CFONT_REALIZATION;
1120 }
1121 i++;
1122 }
1123 while ( i < GDI_CFONT_MAX );
1124 }
1125 return Ret;
1126 }
1127
1128
1129 HFONT
1130 APIENTRY
1131 HfontCreate(
1132 IN PENUMLOGFONTEXDVW pelfw,
1133 IN ULONG cjElfw,
1134 IN LFTYPE lft,
1135 IN FLONG fl,
1136 IN PVOID pvCliData )
1137 {
1138 HFONT hNewFont;
1139 PLFONT plfont;
1140
1141 if (!pelfw)
1142 {
1143 return NULL;
1144 }
1145
1146 plfont = LFONT_AllocFontWithHandle();
1147 if (!plfont)
1148 {
1149 return NULL;
1150 }
1151 hNewFont = plfont->BaseObject.hHmgr;
1152
1153 plfont->lft = lft;
1154 plfont->fl = fl;
1155 RtlCopyMemory (&plfont->logfont, pelfw, sizeof(ENUMLOGFONTEXDVW));
1156 ExInitializePushLock(&plfont->lock);
1157
1158 if (pelfw->elfEnumLogfontEx.elfLogFont.lfEscapement !=
1159 pelfw->elfEnumLogfontEx.elfLogFont.lfOrientation)
1160 {
1161 /* This should really depend on whether GM_ADVANCED is set */
1162 plfont->logfont.elfEnumLogfontEx.elfLogFont.lfOrientation =
1163 plfont->logfont.elfEnumLogfontEx.elfLogFont.lfEscapement;
1164 }
1165 LFONT_UnlockFont(plfont);
1166
1167 if (pvCliData && hNewFont)
1168 {
1169 // FIXME: Use GDIOBJ_InsertUserData
1170 KeEnterCriticalRegion();
1171 {
1172 INT Index = GDI_HANDLE_GET_INDEX((HGDIOBJ)hNewFont);
1173 PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index];
1174 Entry->UserData = pvCliData;
1175 }
1176 KeLeaveCriticalRegion();
1177 }
1178
1179 return hNewFont;
1180 }
1181
1182
1183 HFONT
1184 APIENTRY
1185 NtGdiHfontCreate(
1186 IN PENUMLOGFONTEXDVW pelfw,
1187 IN ULONG cjElfw,
1188 IN LFTYPE lft,
1189 IN FLONG fl,
1190 IN PVOID pvCliData )
1191 {
1192 ENUMLOGFONTEXDVW SafeLogfont;
1193 NTSTATUS Status = STATUS_SUCCESS;
1194
1195 /* Silence GCC warnings */
1196 SafeLogfont.elfEnumLogfontEx.elfLogFont.lfEscapement = 0;
1197 SafeLogfont.elfEnumLogfontEx.elfLogFont.lfOrientation = 0;
1198
1199 if (!pelfw)
1200 {
1201 return NULL;
1202 }
1203
1204 _SEH2_TRY
1205 {
1206 ProbeForRead(pelfw, sizeof(ENUMLOGFONTEXDVW), 1);
1207 RtlCopyMemory(&SafeLogfont, pelfw, sizeof(ENUMLOGFONTEXDVW));
1208 }
1209 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1210 {
1211 Status = _SEH2_GetExceptionCode();
1212 }
1213 _SEH2_END
1214
1215 if (!NT_SUCCESS(Status))
1216 {
1217 return NULL;
1218 }
1219
1220 return HfontCreate(&SafeLogfont, cjElfw, lft, fl, pvCliData);
1221 }
1222
1223
1224 /* EOF */