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 DPRINT1("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 = ExAllocatePoolWithTag(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 IntGetOutlineTextMetrics(FontGDI, Size, potm); 931 932 _SEH2_TRY 933 { 934 ProbeForWrite(otm, Size, 1); 935 RtlCopyMemory(otm, potm, Size); 936 } 937 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 938 { 939 Status = _SEH2_GetExceptionCode(); 940 } 941 _SEH2_END 942 943 if (!NT_SUCCESS(Status)) 944 { 945 EngSetLastError(ERROR_INVALID_PARAMETER); 946 Size = 0; 947 } 948 949 ExFreePoolWithTag(potm,GDITAG_TEXT); 950 return Size; 951 } 952 953 W32KAPI 954 BOOL 955 APIENTRY 956 NtGdiGetFontResourceInfoInternalW( 957 IN LPWSTR pwszFiles, 958 IN ULONG cwc, 959 IN ULONG cFiles, 960 IN UINT cjIn, 961 IN OUT LPDWORD pdwBytes, 962 OUT LPVOID pvBuf, 963 IN DWORD dwType) 964 { 965 NTSTATUS Status = STATUS_SUCCESS; 966 DWORD dwBytes, dwBytesRequested; 967 UNICODE_STRING SafeFileNames; 968 BOOL bRet = FALSE; 969 ULONG cbStringSize; 970 LPVOID Buffer; 971 972 /* FIXME: Handle cFiles > 0 */ 973 974 /* Check for valid dwType values */ 975 if (dwType > 5) 976 { 977 EngSetLastError(ERROR_INVALID_PARAMETER); 978 return FALSE; 979 } 980 981 /* Allocate a safe unicode string buffer */ 982 cbStringSize = cwc * sizeof(WCHAR); 983 SafeFileNames.MaximumLength = SafeFileNames.Length = (USHORT)cbStringSize - sizeof(WCHAR); 984 SafeFileNames.Buffer = ExAllocatePoolWithTag(PagedPool, 985 cbStringSize, 986 TAG_USTR); 987 if (!SafeFileNames.Buffer) 988 { 989 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); 990 return FALSE; 991 } 992 RtlZeroMemory(SafeFileNames.Buffer, SafeFileNames.MaximumLength); 993 994 /* Check buffers and copy pwszFiles to safe unicode string */ 995 _SEH2_TRY 996 { 997 ProbeForRead(pwszFiles, cbStringSize, 1); 998 ProbeForWrite(pdwBytes, sizeof(DWORD), 1); 999 if (pvBuf) 1000 ProbeForWrite(pvBuf, cjIn, 1); 1001 1002 dwBytes = *pdwBytes; 1003 dwBytesRequested = dwBytes; 1004 1005 RtlCopyMemory(SafeFileNames.Buffer, pwszFiles, cbStringSize); 1006 if (dwBytes > 0) 1007 { 1008 Buffer = ExAllocatePoolWithTag(PagedPool, dwBytes, TAG_FINF); 1009 } 1010 else 1011 { 1012 Buffer = ExAllocatePoolWithTag(PagedPool, sizeof(DWORD), TAG_FINF); 1013 } 1014 } 1015 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1016 { 1017 Status = _SEH2_GetExceptionCode(); 1018 } 1019 _SEH2_END 1020 1021 if(!NT_SUCCESS(Status)) 1022 { 1023 SetLastNtError(Status); 1024 /* Free the string buffer for the safe filename */ 1025 ExFreePoolWithTag(SafeFileNames.Buffer, TAG_USTR); 1026 return FALSE; 1027 } 1028 1029 /* Do the actual call */ 1030 bRet = IntGdiGetFontResourceInfo(&SafeFileNames, 1031 (pvBuf ? Buffer : NULL), 1032 &dwBytes, dwType); 1033 1034 /* Check if succeeded */ 1035 if (bRet) 1036 { 1037 /* Copy the data back to caller */ 1038 _SEH2_TRY 1039 { 1040 /* Buffers are already probed */ 1041 if (pvBuf && dwBytesRequested > 0) 1042 RtlCopyMemory(pvBuf, Buffer, min(dwBytesRequested, dwBytes)); 1043 *pdwBytes = dwBytes; 1044 } 1045 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1046 { 1047 Status = _SEH2_GetExceptionCode(); 1048 } 1049 _SEH2_END 1050 1051 if(!NT_SUCCESS(Status)) 1052 { 1053 SetLastNtError(Status); 1054 bRet = FALSE; 1055 } 1056 } 1057 1058 ExFreePoolWithTag(Buffer, TAG_FINF); 1059 /* Free the string for the safe filenames */ 1060 ExFreePoolWithTag(SafeFileNames.Buffer, TAG_USTR); 1061 1062 return bRet; 1063 } 1064 1065 /* 1066 * @unimplemented 1067 */ 1068 BOOL 1069 APIENTRY 1070 NtGdiGetRealizationInfo( 1071 IN HDC hdc, 1072 OUT PREALIZATION_INFO pri, 1073 IN HFONT hf) 1074 { 1075 PDC pDc; 1076 PTEXTOBJ pTextObj; 1077 PFONTGDI pFontGdi; 1078 PDC_ATTR pdcattr; 1079 BOOL Ret = FALSE; 1080 INT i = 0; 1081 REALIZATION_INFO ri; 1082 1083 pDc = DC_LockDc(hdc); 1084 if (!pDc) 1085 { 1086 EngSetLastError(ERROR_INVALID_HANDLE); 1087 return 0; 1088 } 1089 pdcattr = pDc->pdcattr; 1090 pTextObj = RealizeFontInit(pdcattr->hlfntNew); 1091 ASSERT(pTextObj != NULL); 1092 pFontGdi = ObjToGDI(pTextObj->Font, FONT); 1093 TEXTOBJ_UnlockText(pTextObj); 1094 DC_UnlockDc(pDc); 1095 1096 Ret = ftGdiRealizationInfo(pFontGdi, &ri); 1097 if (Ret) 1098 { 1099 if (pri) 1100 { 1101 NTSTATUS Status = STATUS_SUCCESS; 1102 _SEH2_TRY 1103 { 1104 ProbeForWrite(pri, sizeof(REALIZATION_INFO), 1); 1105 RtlCopyMemory(pri, &ri, sizeof(REALIZATION_INFO)); 1106 } 1107 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1108 { 1109 Status = _SEH2_GetExceptionCode(); 1110 } 1111 _SEH2_END 1112 1113 if(!NT_SUCCESS(Status)) 1114 { 1115 SetLastNtError(Status); 1116 return FALSE; 1117 } 1118 } 1119 do 1120 { 1121 if (GdiHandleTable->cfPublic[i].hf == hf) 1122 { 1123 GdiHandleTable->cfPublic[i].iTechnology = ri.iTechnology; 1124 GdiHandleTable->cfPublic[i].iUniq = ri.iUniq; 1125 GdiHandleTable->cfPublic[i].dwUnknown = ri.dwUnknown; 1126 GdiHandleTable->cfPublic[i].dwCFCount = GdiHandleTable->dwCFCount; 1127 GdiHandleTable->cfPublic[i].fl |= CFONT_REALIZATION; 1128 } 1129 i++; 1130 } 1131 while ( i < GDI_CFONT_MAX ); 1132 } 1133 return Ret; 1134 } 1135 1136 1137 HFONT 1138 APIENTRY 1139 HfontCreate( 1140 IN PENUMLOGFONTEXDVW pelfw, 1141 IN ULONG cjElfw, 1142 IN LFTYPE lft, 1143 IN FLONG fl, 1144 IN PVOID pvCliData ) 1145 { 1146 HFONT hNewFont; 1147 PLFONT plfont; 1148 1149 if (!pelfw) 1150 { 1151 return NULL; 1152 } 1153 1154 plfont = LFONT_AllocFontWithHandle(); 1155 if (!plfont) 1156 { 1157 return NULL; 1158 } 1159 hNewFont = plfont->BaseObject.hHmgr; 1160 1161 plfont->lft = lft; 1162 plfont->fl = fl; 1163 RtlCopyMemory (&plfont->logfont, pelfw, sizeof(ENUMLOGFONTEXDVW)); 1164 ExInitializePushLock(&plfont->lock); 1165 1166 if (pelfw->elfEnumLogfontEx.elfLogFont.lfEscapement != 1167 pelfw->elfEnumLogfontEx.elfLogFont.lfOrientation) 1168 { 1169 /* This should really depend on whether GM_ADVANCED is set */ 1170 plfont->logfont.elfEnumLogfontEx.elfLogFont.lfOrientation = 1171 plfont->logfont.elfEnumLogfontEx.elfLogFont.lfEscapement; 1172 } 1173 LFONT_UnlockFont(plfont); 1174 1175 if (pvCliData && hNewFont) 1176 { 1177 // FIXME: Use GDIOBJ_InsertUserData 1178 KeEnterCriticalRegion(); 1179 { 1180 INT Index = GDI_HANDLE_GET_INDEX((HGDIOBJ)hNewFont); 1181 PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index]; 1182 Entry->UserData = pvCliData; 1183 } 1184 KeLeaveCriticalRegion(); 1185 } 1186 1187 return hNewFont; 1188 } 1189 1190 1191 HFONT 1192 APIENTRY 1193 NtGdiHfontCreate( 1194 IN PENUMLOGFONTEXDVW pelfw, 1195 IN ULONG cjElfw, 1196 IN LFTYPE lft, 1197 IN FLONG fl, 1198 IN PVOID pvCliData ) 1199 { 1200 ENUMLOGFONTEXDVW SafeLogfont; 1201 NTSTATUS Status = STATUS_SUCCESS; 1202 1203 /* Silence GCC warnings */ 1204 SafeLogfont.elfEnumLogfontEx.elfLogFont.lfEscapement = 0; 1205 SafeLogfont.elfEnumLogfontEx.elfLogFont.lfOrientation = 0; 1206 1207 if (!pelfw) 1208 { 1209 return NULL; 1210 } 1211 1212 _SEH2_TRY 1213 { 1214 ProbeForRead(pelfw, sizeof(ENUMLOGFONTEXDVW), 1); 1215 RtlCopyMemory(&SafeLogfont, pelfw, sizeof(ENUMLOGFONTEXDVW)); 1216 } 1217 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1218 { 1219 Status = _SEH2_GetExceptionCode(); 1220 } 1221 _SEH2_END 1222 1223 if (!NT_SUCCESS(Status)) 1224 { 1225 return NULL; 1226 } 1227 1228 return HfontCreate(&SafeLogfont, cjElfw, lft, fl, pvCliData); 1229 } 1230 1231 1232 /* EOF */ 1233