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 M$ 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 buffer is NULL, only the size is requested */ 299 if (pvBuffer == NULL) return sizeof(LOGFONTW); 300 301 /* Calculate the maximum size according to number of axes */ 302 cjMaxSize = FIELD_OFFSET(ENUMLOGFONTEXDVW, 303 elfDesignVector.dvValues[plf->elfDesignVector.dvNumAxes]); 304 305 if (cjBuffer > cjMaxSize) cjBuffer = cjMaxSize; 306 307 RtlCopyMemory(pvBuffer, plf, cjBuffer); 308 309 return cjBuffer; 310 } 311 312 DWORD 313 FASTCALL 314 IntGetCharDimensions(HDC hdc, PTEXTMETRICW ptm, PDWORD height) 315 { 316 PDC pdc; 317 PDC_ATTR pdcattr; 318 PTEXTOBJ TextObj; 319 SIZE sz; 320 TMW_INTERNAL tmwi; 321 BOOL Good; 322 323 static const WCHAR alphabet[] = { 324 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q', 325 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H', 326 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0}; 327 328 if(!ftGdiGetTextMetricsW(hdc, &tmwi)) return 0; 329 330 pdc = DC_LockDc(hdc); 331 332 if (!pdc) return 0; 333 334 pdcattr = pdc->pdcattr; 335 336 TextObj = RealizeFontInit(pdcattr->hlfntNew); 337 if ( !TextObj ) 338 { 339 DC_UnlockDc(pdc); 340 return 0; 341 } 342 Good = TextIntGetTextExtentPoint(pdc, TextObj, alphabet, 52, 0, NULL, 0, &sz, 0); 343 TEXTOBJ_UnlockText(TextObj); 344 DC_UnlockDc(pdc); 345 346 if (!Good) return 0; 347 if (ptm) *ptm = tmwi.TextMetric; 348 if (height) *height = tmwi.TextMetric.tmHeight; 349 350 return (sz.cx / 26 + 1) / 2; 351 } 352 353 354 DWORD 355 FASTCALL 356 IntGetFontLanguageInfo(PDC Dc) 357 { 358 PDC_ATTR pdcattr; 359 FONTSIGNATURE fontsig; 360 static const DWORD GCP_DBCS_MASK=0x003F0000, 361 GCP_DIACRITIC_MASK=0x00000000, 362 FLI_GLYPHS_MASK=0x00000000, 363 GCP_GLYPHSHAPE_MASK=0x00000040, 364 GCP_KASHIDA_MASK=0x00000000, 365 GCP_LIGATE_MASK=0x00000000, 366 GCP_USEKERNING_MASK=0x00000000, 367 GCP_REORDER_MASK=0x00000060; 368 369 DWORD result=0; 370 371 ftGdiGetTextCharsetInfo( Dc, &fontsig, 0 ); 372 373 /* We detect each flag we return using a bitmask on the Codepage Bitfields */ 374 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 ) 375 result|=GCP_DBCS; 376 377 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 ) 378 result|=GCP_DIACRITIC; 379 380 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 ) 381 result|=FLI_GLYPHS; 382 383 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 ) 384 result|=GCP_GLYPHSHAPE; 385 386 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 ) 387 result|=GCP_KASHIDA; 388 389 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 ) 390 result|=GCP_LIGATE; 391 392 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 ) 393 result|=GCP_USEKERNING; 394 395 pdcattr = Dc->pdcattr; 396 397 /* This might need a test for a HEBREW- or ARABIC_CHARSET as well */ 398 if ( pdcattr->lTextAlign & TA_RTLREADING ) 399 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 ) 400 result|=GCP_REORDER; 401 402 return result; 403 } 404 405 PTEXTOBJ 406 FASTCALL 407 RealizeFontInit(HFONT hFont) 408 { 409 NTSTATUS Status = STATUS_SUCCESS; 410 PTEXTOBJ pTextObj; 411 412 pTextObj = TEXTOBJ_LockText(hFont); 413 414 if ( pTextObj && !(pTextObj->fl & TEXTOBJECT_INIT)) 415 { 416 Status = TextIntRealizeFont(hFont, pTextObj); 417 if (!NT_SUCCESS(Status)) 418 { 419 TEXTOBJ_UnlockText(pTextObj); 420 return NULL; 421 } 422 } 423 return pTextObj; 424 } 425 426 427 /** Functions ******************************************************************/ 428 429 INT 430 APIENTRY 431 NtGdiAddFontResourceW( 432 IN WCHAR *pwcFiles, 433 IN ULONG cwc, 434 IN ULONG cFiles, 435 IN FLONG fl, 436 IN DWORD dwPidTid, 437 IN OPTIONAL DESIGNVECTOR *pdv) 438 { 439 UNICODE_STRING SafeFileName; 440 INT Ret; 441 442 DBG_UNREFERENCED_PARAMETER(cFiles); 443 DBG_UNREFERENCED_PARAMETER(dwPidTid); 444 DBG_UNREFERENCED_PARAMETER(pdv); 445 446 DPRINT("NtGdiAddFontResourceW\n"); 447 448 /* cwc = Length + trailing zero. */ 449 if ((cwc <= 1) || (cwc > UNICODE_STRING_MAX_CHARS)) 450 return 0; 451 452 SafeFileName.MaximumLength = (USHORT)(cwc * sizeof(WCHAR)); 453 SafeFileName.Length = SafeFileName.MaximumLength - sizeof(UNICODE_NULL); 454 SafeFileName.Buffer = ExAllocatePoolWithTag(PagedPool, 455 SafeFileName.MaximumLength, 456 TAG_STRING); 457 if (!SafeFileName.Buffer) 458 { 459 return 0; 460 } 461 462 _SEH2_TRY 463 { 464 ProbeForRead(pwcFiles, cwc * sizeof(WCHAR), sizeof(WCHAR)); 465 RtlCopyMemory(SafeFileName.Buffer, pwcFiles, SafeFileName.Length); 466 } 467 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 468 { 469 ExFreePoolWithTag(SafeFileName.Buffer, TAG_STRING); 470 _SEH2_YIELD(return 0); 471 } 472 _SEH2_END; 473 474 SafeFileName.Buffer[SafeFileName.Length / sizeof(WCHAR)] = UNICODE_NULL; 475 Ret = IntGdiAddFontResource(&SafeFileName, fl); 476 477 ExFreePoolWithTag(SafeFileName.Buffer, TAG_STRING); 478 return Ret; 479 } 480 481 HANDLE 482 APIENTRY 483 NtGdiAddFontMemResourceEx( 484 IN PVOID pvBuffer, 485 IN DWORD cjBuffer, 486 IN DESIGNVECTOR *pdv, 487 IN ULONG cjDV, 488 OUT DWORD *pNumFonts) 489 { 490 _SEH2_VOLATILE PVOID Buffer = NULL; 491 HANDLE Ret; 492 DWORD NumFonts = 0; 493 494 DPRINT("NtGdiAddFontMemResourceEx\n"); 495 DBG_UNREFERENCED_PARAMETER(pdv); 496 DBG_UNREFERENCED_PARAMETER(cjDV); 497 498 if (!pvBuffer || !cjBuffer) 499 return NULL; 500 501 _SEH2_TRY 502 { 503 ProbeForRead(pvBuffer, cjBuffer, sizeof(BYTE)); 504 Buffer = ExAllocatePoolWithQuotaTag(PagedPool, cjBuffer, TAG_FONT); 505 RtlCopyMemory(Buffer, pvBuffer, cjBuffer); 506 } 507 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 508 { 509 if (Buffer != NULL) 510 { 511 ExFreePoolWithTag(Buffer, TAG_FONT); 512 } 513 _SEH2_YIELD(return NULL); 514 } 515 _SEH2_END; 516 517 Ret = IntGdiAddFontMemResource(Buffer, cjBuffer, &NumFonts); 518 ExFreePoolWithTag(Buffer, TAG_FONT); 519 520 _SEH2_TRY 521 { 522 ProbeForWrite(pNumFonts, sizeof(NumFonts), 1); 523 *pNumFonts = NumFonts; 524 } 525 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 526 { 527 /* Leak it? */ 528 _SEH2_YIELD(return NULL); 529 } 530 _SEH2_END; 531 532 533 return Ret; 534 } 535 536 537 BOOL 538 APIENTRY 539 NtGdiRemoveFontMemResourceEx( 540 IN HANDLE hMMFont) 541 { 542 return IntGdiRemoveFontMemResource(hMMFont); 543 } 544 545 546 /* 547 * @unimplemented 548 */ 549 DWORD 550 APIENTRY 551 NtGdiGetCharacterPlacementW( 552 IN HDC hdc, 553 IN LPWSTR pwsz, 554 IN INT nCount, 555 IN INT nMaxExtent, 556 IN OUT LPGCP_RESULTSW pgcpw, 557 IN DWORD dwFlags) 558 { 559 UNIMPLEMENTED; 560 return 0; 561 #if 0 562 return GreGetCharacterPlacementW( hdc, 563 pwsz, 564 nCount, 565 nMaxExtent, 566 pgcpw, 567 dwFlags); 568 #endif 569 } 570 571 DWORD 572 APIENTRY 573 NtGdiGetFontData( 574 HDC hDC, 575 DWORD Table, 576 DWORD Offset, 577 LPVOID Buffer, 578 DWORD Size) 579 { 580 PDC Dc; 581 PDC_ATTR pdcattr; 582 HFONT hFont; 583 PTEXTOBJ TextObj; 584 PFONTGDI FontGdi; 585 DWORD Result = GDI_ERROR; 586 NTSTATUS Status = STATUS_SUCCESS; 587 588 if (Buffer && Size) 589 { 590 _SEH2_TRY 591 { 592 ProbeForRead(Buffer, Size, 1); 593 } 594 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 595 { 596 Status = _SEH2_GetExceptionCode(); 597 } 598 _SEH2_END 599 } 600 601 if (!NT_SUCCESS(Status)) return Result; 602 603 Dc = DC_LockDc(hDC); 604 if (Dc == NULL) 605 { 606 EngSetLastError(ERROR_INVALID_HANDLE); 607 return GDI_ERROR; 608 } 609 pdcattr = Dc->pdcattr; 610 611 hFont = pdcattr->hlfntNew; 612 TextObj = RealizeFontInit(hFont); 613 DC_UnlockDc(Dc); 614 615 if (TextObj == NULL) 616 { 617 EngSetLastError(ERROR_INVALID_HANDLE); 618 return GDI_ERROR; 619 } 620 621 FontGdi = ObjToGDI(TextObj->Font, FONT); 622 623 Result = ftGdiGetFontData(FontGdi, Table, Offset, Buffer, Size); 624 625 TEXTOBJ_UnlockText(TextObj); 626 627 return Result; 628 } 629 630 /* 631 * @implemented 632 */ 633 DWORD 634 APIENTRY 635 NtGdiGetFontUnicodeRanges( 636 IN HDC hdc, 637 OUT OPTIONAL LPGLYPHSET pgs) 638 { 639 PDC pDc; 640 PDC_ATTR pdcattr; 641 HFONT hFont; 642 PTEXTOBJ TextObj; 643 PFONTGDI FontGdi; 644 DWORD Size = 0; 645 PGLYPHSET pgsSafe; 646 NTSTATUS Status = STATUS_SUCCESS; 647 648 pDc = DC_LockDc(hdc); 649 if (!pDc) 650 { 651 EngSetLastError(ERROR_INVALID_HANDLE); 652 return 0; 653 } 654 655 pdcattr = pDc->pdcattr; 656 657 hFont = pdcattr->hlfntNew; 658 TextObj = RealizeFontInit(hFont); 659 660 if ( TextObj == NULL) 661 { 662 EngSetLastError(ERROR_INVALID_HANDLE); 663 goto Exit; 664 } 665 FontGdi = ObjToGDI(TextObj->Font, FONT); 666 667 Size = ftGetFontUnicodeRanges( FontGdi, NULL); 668 669 if (Size && pgs) 670 { 671 pgsSafe = ExAllocatePoolWithTag(PagedPool, Size, GDITAG_TEXT); 672 if (!pgsSafe) 673 { 674 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); 675 Size = 0; 676 goto Exit; 677 } 678 679 Size = ftGetFontUnicodeRanges( FontGdi, pgsSafe); 680 681 if (Size) 682 { 683 _SEH2_TRY 684 { 685 ProbeForWrite(pgs, Size, 1); 686 RtlCopyMemory(pgs, pgsSafe, Size); 687 } 688 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 689 { 690 Status = _SEH2_GetExceptionCode(); 691 } 692 _SEH2_END 693 694 if (!NT_SUCCESS(Status)) Size = 0; 695 } 696 ExFreePoolWithTag(pgsSafe, GDITAG_TEXT); 697 } 698 Exit: 699 TEXTOBJ_UnlockText(TextObj); 700 DC_UnlockDc(pDc); 701 return Size; 702 } 703 704 ULONG 705 APIENTRY 706 NtGdiGetGlyphOutline( 707 IN HDC hdc, 708 IN WCHAR wch, 709 IN UINT iFormat, 710 OUT LPGLYPHMETRICS pgm, 711 IN ULONG cjBuf, 712 OUT OPTIONAL PVOID UnsafeBuf, 713 IN LPMAT2 pmat2, 714 IN BOOL bIgnoreRotation) 715 { 716 ULONG Ret = GDI_ERROR; 717 PDC dc; 718 PVOID pvBuf = NULL; 719 GLYPHMETRICS gm; 720 NTSTATUS Status = STATUS_SUCCESS; 721 722 dc = DC_LockDc(hdc); 723 if (!dc) 724 { 725 EngSetLastError(ERROR_INVALID_HANDLE); 726 return GDI_ERROR; 727 } 728 729 if (UnsafeBuf && cjBuf) 730 { 731 pvBuf = ExAllocatePoolWithTag(PagedPool, cjBuf, GDITAG_TEXT); 732 if (!pvBuf) 733 { 734 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); 735 goto Exit; 736 } 737 } 738 739 Ret = ftGdiGetGlyphOutline( dc, 740 wch, 741 iFormat, 742 pgm ? &gm : NULL, 743 cjBuf, 744 pvBuf, 745 pmat2, 746 bIgnoreRotation); 747 748 if (pvBuf) 749 { 750 _SEH2_TRY 751 { 752 ProbeForWrite(UnsafeBuf, cjBuf, 1); 753 RtlCopyMemory(UnsafeBuf, pvBuf, cjBuf); 754 } 755 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 756 { 757 Status = _SEH2_GetExceptionCode(); 758 } 759 _SEH2_END 760 761 ExFreePoolWithTag(pvBuf, GDITAG_TEXT); 762 } 763 764 if (pgm) 765 { 766 _SEH2_TRY 767 { 768 ProbeForWrite(pgm, sizeof(GLYPHMETRICS), 1); 769 RtlCopyMemory(pgm, &gm, sizeof(GLYPHMETRICS)); 770 } 771 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 772 { 773 Status = _SEH2_GetExceptionCode(); 774 } 775 _SEH2_END 776 } 777 778 if (! NT_SUCCESS(Status)) 779 { 780 EngSetLastError(ERROR_INVALID_PARAMETER); 781 Ret = GDI_ERROR; 782 } 783 784 Exit: 785 DC_UnlockDc(dc); 786 return Ret; 787 } 788 789 DWORD 790 APIENTRY 791 NtGdiGetKerningPairs(HDC hDC, 792 ULONG NumPairs, 793 LPKERNINGPAIR krnpair) 794 { 795 PDC dc; 796 PDC_ATTR pdcattr; 797 PTEXTOBJ TextObj; 798 PFONTGDI FontGDI; 799 DWORD Count; 800 KERNINGPAIR *pKP; 801 NTSTATUS Status = STATUS_SUCCESS; 802 803 dc = DC_LockDc(hDC); 804 if (!dc) 805 { 806 EngSetLastError(ERROR_INVALID_HANDLE); 807 return 0; 808 } 809 810 pdcattr = dc->pdcattr; 811 TextObj = RealizeFontInit(pdcattr->hlfntNew); 812 DC_UnlockDc(dc); 813 814 if (!TextObj) 815 { 816 EngSetLastError(ERROR_INVALID_HANDLE); 817 return 0; 818 } 819 820 FontGDI = ObjToGDI(TextObj->Font, FONT); 821 TEXTOBJ_UnlockText(TextObj); 822 823 Count = ftGdiGetKerningPairs(FontGDI,0,NULL); 824 825 if ( Count && krnpair ) 826 { 827 if (Count > NumPairs) 828 { 829 EngSetLastError(ERROR_INSUFFICIENT_BUFFER); 830 return 0; 831 } 832 pKP = ExAllocatePoolWithTag(PagedPool, Count * sizeof(KERNINGPAIR), GDITAG_TEXT); 833 if (!pKP) 834 { 835 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); 836 return 0; 837 } 838 ftGdiGetKerningPairs(FontGDI,Count,pKP); 839 _SEH2_TRY 840 { 841 ProbeForWrite(krnpair, Count * sizeof(KERNINGPAIR), 1); 842 RtlCopyMemory(krnpair, pKP, Count * sizeof(KERNINGPAIR)); 843 } 844 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 845 { 846 Status = _SEH2_GetExceptionCode(); 847 } 848 _SEH2_END 849 if (!NT_SUCCESS(Status)) 850 { 851 EngSetLastError(ERROR_INVALID_PARAMETER); 852 Count = 0; 853 } 854 ExFreePoolWithTag(pKP,GDITAG_TEXT); 855 } 856 return Count; 857 } 858 859 /* 860 From "Undocumented Windows 2000 Secrets" Appendix B, Table B-2, page 861 472, this is NtGdiGetOutlineTextMetricsInternalW. 862 */ 863 ULONG 864 APIENTRY 865 NtGdiGetOutlineTextMetricsInternalW (HDC hDC, 866 ULONG Data, 867 OUTLINETEXTMETRICW *otm, 868 TMDIFF *Tmd) 869 { 870 PDC dc; 871 PDC_ATTR pdcattr; 872 PTEXTOBJ TextObj; 873 PFONTGDI FontGDI; 874 HFONT hFont = 0; 875 ULONG Size; 876 OUTLINETEXTMETRICW *potm; 877 NTSTATUS Status = STATUS_SUCCESS; 878 879 dc = DC_LockDc(hDC); 880 if (!dc) 881 { 882 EngSetLastError(ERROR_INVALID_HANDLE); 883 return 0; 884 } 885 pdcattr = dc->pdcattr; 886 hFont = pdcattr->hlfntNew; 887 TextObj = RealizeFontInit(hFont); 888 DC_UnlockDc(dc); 889 if (!TextObj) 890 { 891 EngSetLastError(ERROR_INVALID_HANDLE); 892 return 0; 893 } 894 FontGDI = ObjToGDI(TextObj->Font, FONT); 895 TextIntUpdateSize(dc, TextObj, FontGDI, TRUE); 896 TEXTOBJ_UnlockText(TextObj); 897 Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL); 898 if (!otm) return Size; 899 if (Size > Data) 900 { 901 EngSetLastError(ERROR_INSUFFICIENT_BUFFER); 902 return 0; 903 } 904 potm = ExAllocatePoolWithTag(PagedPool, Size, GDITAG_TEXT); 905 if (!potm) 906 { 907 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); 908 return 0; 909 } 910 IntGetOutlineTextMetrics(FontGDI, Size, potm); 911 if (otm) 912 { 913 _SEH2_TRY 914 { 915 ProbeForWrite(otm, Size, 1); 916 RtlCopyMemory(otm, potm, Size); 917 } 918 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 919 { 920 Status = _SEH2_GetExceptionCode(); 921 } 922 _SEH2_END 923 924 if (!NT_SUCCESS(Status)) 925 { 926 EngSetLastError(ERROR_INVALID_PARAMETER); 927 Size = 0; 928 } 929 } 930 ExFreePoolWithTag(potm,GDITAG_TEXT); 931 return Size; 932 } 933 934 W32KAPI 935 BOOL 936 APIENTRY 937 NtGdiGetFontResourceInfoInternalW( 938 IN LPWSTR pwszFiles, 939 IN ULONG cwc, 940 IN ULONG cFiles, 941 IN UINT cjIn, 942 IN OUT LPDWORD pdwBytes, 943 OUT LPVOID pvBuf, 944 IN DWORD dwType) 945 { 946 NTSTATUS Status = STATUS_SUCCESS; 947 DWORD dwBytes, dwBytesRequested; 948 UNICODE_STRING SafeFileNames; 949 BOOL bRet = FALSE; 950 ULONG cbStringSize; 951 LPVOID Buffer; 952 953 /* FIXME: Handle cFiles > 0 */ 954 955 /* Check for valid dwType values */ 956 if (dwType > 5) 957 { 958 EngSetLastError(ERROR_INVALID_PARAMETER); 959 return FALSE; 960 } 961 962 /* Allocate a safe unicode string buffer */ 963 cbStringSize = cwc * sizeof(WCHAR); 964 SafeFileNames.MaximumLength = SafeFileNames.Length = (USHORT)cbStringSize - sizeof(WCHAR); 965 SafeFileNames.Buffer = ExAllocatePoolWithTag(PagedPool, 966 cbStringSize, 967 TAG_USTR); 968 if (!SafeFileNames.Buffer) 969 { 970 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); 971 return FALSE; 972 } 973 RtlZeroMemory(SafeFileNames.Buffer, SafeFileNames.MaximumLength); 974 975 /* Check buffers and copy pwszFiles to safe unicode string */ 976 _SEH2_TRY 977 { 978 ProbeForRead(pwszFiles, cbStringSize, 1); 979 ProbeForWrite(pdwBytes, sizeof(DWORD), 1); 980 if (pvBuf) 981 ProbeForWrite(pvBuf, cjIn, 1); 982 983 dwBytes = *pdwBytes; 984 dwBytesRequested = dwBytes; 985 986 RtlCopyMemory(SafeFileNames.Buffer, pwszFiles, cbStringSize); 987 if (dwBytes > 0) 988 { 989 Buffer = ExAllocatePoolWithTag(PagedPool, dwBytes, TAG_FINF); 990 } 991 else 992 { 993 Buffer = ExAllocatePoolWithTag(PagedPool, sizeof(DWORD), TAG_FINF); 994 } 995 } 996 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 997 { 998 Status = _SEH2_GetExceptionCode(); 999 } 1000 _SEH2_END 1001 1002 if(!NT_SUCCESS(Status)) 1003 { 1004 SetLastNtError(Status); 1005 /* Free the string buffer for the safe filename */ 1006 ExFreePoolWithTag(SafeFileNames.Buffer, TAG_USTR); 1007 return FALSE; 1008 } 1009 1010 /* Do the actual call */ 1011 bRet = IntGdiGetFontResourceInfo(&SafeFileNames, 1012 (pvBuf ? Buffer : NULL), 1013 &dwBytes, dwType); 1014 1015 /* Check if succeeded */ 1016 if (bRet) 1017 { 1018 /* Copy the data back to caller */ 1019 _SEH2_TRY 1020 { 1021 /* Buffers are already probed */ 1022 if (pvBuf && dwBytesRequested > 0) 1023 RtlCopyMemory(pvBuf, Buffer, min(dwBytesRequested, dwBytes)); 1024 *pdwBytes = dwBytes; 1025 } 1026 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1027 { 1028 Status = _SEH2_GetExceptionCode(); 1029 } 1030 _SEH2_END 1031 1032 if(!NT_SUCCESS(Status)) 1033 { 1034 SetLastNtError(Status); 1035 bRet = FALSE; 1036 } 1037 } 1038 1039 ExFreePoolWithTag(Buffer, TAG_FINF); 1040 /* Free the string for the safe filenames */ 1041 ExFreePoolWithTag(SafeFileNames.Buffer, TAG_USTR); 1042 1043 return bRet; 1044 } 1045 1046 /* 1047 * @unimplemented 1048 */ 1049 BOOL 1050 APIENTRY 1051 NtGdiGetRealizationInfo( 1052 IN HDC hdc, 1053 OUT PREALIZATION_INFO pri, 1054 IN HFONT hf) 1055 { 1056 PDC pDc; 1057 PTEXTOBJ pTextObj; 1058 PFONTGDI pFontGdi; 1059 PDC_ATTR pdcattr; 1060 BOOL Ret = FALSE; 1061 INT i = 0; 1062 REALIZATION_INFO ri; 1063 1064 pDc = DC_LockDc(hdc); 1065 if (!pDc) 1066 { 1067 EngSetLastError(ERROR_INVALID_HANDLE); 1068 return 0; 1069 } 1070 pdcattr = pDc->pdcattr; 1071 pTextObj = RealizeFontInit(pdcattr->hlfntNew); 1072 pFontGdi = ObjToGDI(pTextObj->Font, FONT); 1073 TEXTOBJ_UnlockText(pTextObj); 1074 DC_UnlockDc(pDc); 1075 1076 Ret = ftGdiRealizationInfo(pFontGdi, &ri); 1077 if (Ret) 1078 { 1079 if (pri) 1080 { 1081 NTSTATUS Status = STATUS_SUCCESS; 1082 _SEH2_TRY 1083 { 1084 ProbeForWrite(pri, sizeof(REALIZATION_INFO), 1); 1085 RtlCopyMemory(pri, &ri, sizeof(REALIZATION_INFO)); 1086 } 1087 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1088 { 1089 Status = _SEH2_GetExceptionCode(); 1090 } 1091 _SEH2_END 1092 1093 if(!NT_SUCCESS(Status)) 1094 { 1095 SetLastNtError(Status); 1096 return FALSE; 1097 } 1098 } 1099 do 1100 { 1101 if (GdiHandleTable->cfPublic[i].hf == hf) 1102 { 1103 GdiHandleTable->cfPublic[i].iTechnology = ri.iTechnology; 1104 GdiHandleTable->cfPublic[i].iUniq = ri.iUniq; 1105 GdiHandleTable->cfPublic[i].dwUnknown = ri.dwUnknown; 1106 GdiHandleTable->cfPublic[i].dwCFCount = GdiHandleTable->dwCFCount; 1107 GdiHandleTable->cfPublic[i].fl |= CFONT_REALIZATION; 1108 } 1109 i++; 1110 } 1111 while ( i < GDI_CFONT_MAX ); 1112 } 1113 return Ret; 1114 } 1115 1116 1117 HFONT 1118 APIENTRY 1119 HfontCreate( 1120 IN PENUMLOGFONTEXDVW pelfw, 1121 IN ULONG cjElfw, 1122 IN LFTYPE lft, 1123 IN FLONG fl, 1124 IN PVOID pvCliData ) 1125 { 1126 HFONT hNewFont; 1127 PLFONT plfont; 1128 1129 if (!pelfw) 1130 { 1131 return NULL; 1132 } 1133 1134 plfont = LFONT_AllocFontWithHandle(); 1135 if (!plfont) 1136 { 1137 return NULL; 1138 } 1139 hNewFont = plfont->BaseObject.hHmgr; 1140 1141 plfont->lft = lft; 1142 plfont->fl = fl; 1143 RtlCopyMemory (&plfont->logfont, pelfw, sizeof(ENUMLOGFONTEXDVW)); 1144 ExInitializePushLock(&plfont->lock); 1145 1146 if (pelfw->elfEnumLogfontEx.elfLogFont.lfEscapement != 1147 pelfw->elfEnumLogfontEx.elfLogFont.lfOrientation) 1148 { 1149 /* This should really depend on whether GM_ADVANCED is set */ 1150 plfont->logfont.elfEnumLogfontEx.elfLogFont.lfOrientation = 1151 plfont->logfont.elfEnumLogfontEx.elfLogFont.lfEscapement; 1152 } 1153 LFONT_UnlockFont(plfont); 1154 1155 if (pvCliData && hNewFont) 1156 { 1157 // FIXME: Use GDIOBJ_InsertUserData 1158 KeEnterCriticalRegion(); 1159 { 1160 INT Index = GDI_HANDLE_GET_INDEX((HGDIOBJ)hNewFont); 1161 PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index]; 1162 Entry->UserData = pvCliData; 1163 } 1164 KeLeaveCriticalRegion(); 1165 } 1166 1167 return hNewFont; 1168 } 1169 1170 1171 HFONT 1172 APIENTRY 1173 NtGdiHfontCreate( 1174 IN PENUMLOGFONTEXDVW pelfw, 1175 IN ULONG cjElfw, 1176 IN LFTYPE lft, 1177 IN FLONG fl, 1178 IN PVOID pvCliData ) 1179 { 1180 ENUMLOGFONTEXDVW SafeLogfont; 1181 NTSTATUS Status = STATUS_SUCCESS; 1182 1183 /* Silence GCC warnings */ 1184 SafeLogfont.elfEnumLogfontEx.elfLogFont.lfEscapement = 0; 1185 SafeLogfont.elfEnumLogfontEx.elfLogFont.lfOrientation = 0; 1186 1187 if (!pelfw) 1188 { 1189 return NULL; 1190 } 1191 1192 _SEH2_TRY 1193 { 1194 ProbeForRead(pelfw, sizeof(ENUMLOGFONTEXDVW), 1); 1195 RtlCopyMemory(&SafeLogfont, pelfw, sizeof(ENUMLOGFONTEXDVW)); 1196 } 1197 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1198 { 1199 Status = _SEH2_GetExceptionCode(); 1200 } 1201 _SEH2_END 1202 1203 if (!NT_SUCCESS(Status)) 1204 { 1205 return NULL; 1206 } 1207 1208 return HfontCreate(&SafeLogfont, cjElfw, lft, fl, pvCliData); 1209 } 1210 1211 1212 /* EOF */ 1213