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