1 /* 2 * PROJECT: ReactOS win32 kernel mode subsystem 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: win32ss/gdi/ntgdi/text.c 5 * PURPOSE: Text/Font 6 * PROGRAMMER: 7 */ 8 9 /** Includes ******************************************************************/ 10 11 #include <win32k.h> 12 13 #define NDEBUG 14 #include <debug.h> 15 16 /** Functions *****************************************************************/ 17 18 BOOL FASTCALL 19 GreTextOutW( 20 HDC hdc, 21 int nXStart, 22 int nYStart, 23 LPCWSTR lpString, 24 int cchString) 25 { 26 return GreExtTextOutW(hdc, nXStart, nYStart, 0, NULL, lpString, cchString, NULL, 0); 27 } 28 29 /* 30 flOpts : 31 GetTextExtentPoint32W = 0 32 GetTextExtentPointW = 1 33 */ 34 BOOL 35 FASTCALL 36 GreGetTextExtentW( 37 HDC hDC, 38 LPCWSTR lpwsz, 39 INT cwc, 40 LPSIZE psize, 41 UINT flOpts) 42 { 43 PDC pdc; 44 PDC_ATTR pdcattr; 45 BOOL Result; 46 PTEXTOBJ TextObj; 47 48 if (!cwc) 49 { 50 psize->cx = 0; 51 psize->cy = 0; 52 return TRUE; 53 } 54 55 pdc = DC_LockDc(hDC); 56 if (!pdc) 57 { 58 EngSetLastError(ERROR_INVALID_HANDLE); 59 return FALSE; 60 } 61 62 pdcattr = pdc->pdcattr; 63 64 TextObj = RealizeFontInit(pdcattr->hlfntNew); 65 if ( TextObj ) 66 { 67 Result = TextIntGetTextExtentPoint( pdc, 68 TextObj, 69 lpwsz, 70 cwc, 71 0, 72 NULL, 73 0, 74 psize, 75 flOpts); 76 TEXTOBJ_UnlockText(TextObj); 77 } 78 else 79 Result = FALSE; 80 81 DC_UnlockDc(pdc); 82 return Result; 83 } 84 85 86 /* 87 fl : 88 GetTextExtentExPointW = 0 and everything else that uses this. 89 GetTextExtentExPointI = 1 90 */ 91 BOOL 92 FASTCALL 93 GreGetTextExtentExW( 94 HDC hDC, 95 LPCWSTR String, 96 ULONG Count, 97 ULONG MaxExtent, 98 PULONG Fit, 99 PULONG Dx, 100 LPSIZE pSize, 101 FLONG fl) 102 { 103 PDC pdc; 104 PDC_ATTR pdcattr; 105 BOOL Result; 106 PTEXTOBJ TextObj; 107 108 if ( (!String && Count ) || !pSize ) 109 { 110 EngSetLastError(ERROR_INVALID_PARAMETER); 111 return FALSE; 112 } 113 114 if ( !Count ) 115 { 116 if ( Fit ) Fit = 0; 117 return TRUE; 118 } 119 120 pdc = DC_LockDc(hDC); 121 if (NULL == pdc) 122 { 123 EngSetLastError(ERROR_INVALID_HANDLE); 124 return FALSE; 125 } 126 pdcattr = pdc->pdcattr; 127 128 TextObj = RealizeFontInit(pdcattr->hlfntNew); 129 if ( TextObj ) 130 { 131 Result = TextIntGetTextExtentPoint( pdc, 132 TextObj, 133 String, 134 Count, 135 MaxExtent, 136 (LPINT)Fit, 137 (LPINT)Dx, 138 pSize, 139 fl); 140 TEXTOBJ_UnlockText(TextObj); 141 } 142 else 143 Result = FALSE; 144 145 DC_UnlockDc(pdc); 146 return Result; 147 } 148 149 BOOL 150 WINAPI 151 GreGetTextMetricsW( 152 _In_ HDC hdc, 153 _Out_ LPTEXTMETRICW lptm) 154 { 155 TMW_INTERNAL tmwi; 156 if (!ftGdiGetTextMetricsW(hdc, &tmwi)) return FALSE; 157 *lptm = tmwi.TextMetric; 158 return TRUE; 159 } 160 161 DWORD 162 APIENTRY 163 NtGdiGetCharSet(HDC hDC) 164 { 165 PDC Dc; 166 PDC_ATTR pdcattr; 167 DWORD cscp; 168 // If here, update everything! 169 Dc = DC_LockDc(hDC); 170 if (!Dc) 171 { 172 EngSetLastError(ERROR_INVALID_HANDLE); 173 return 0; 174 } 175 cscp = ftGdiGetTextCharsetInfo(Dc, NULL, 0); 176 pdcattr = Dc->pdcattr; 177 pdcattr->iCS_CP = cscp; 178 pdcattr->ulDirty_ &= ~DIRTY_CHARSET; 179 DC_UnlockDc( Dc ); 180 return cscp; 181 } 182 183 BOOL 184 APIENTRY 185 NtGdiGetRasterizerCaps( 186 OUT LPRASTERIZER_STATUS praststat, 187 IN ULONG cjBytes) 188 { 189 NTSTATUS Status = STATUS_SUCCESS; 190 RASTERIZER_STATUS rsSafe; 191 192 if (praststat && cjBytes) 193 { 194 if ( cjBytes >= sizeof(RASTERIZER_STATUS) ) cjBytes = sizeof(RASTERIZER_STATUS); 195 if ( ftGdiGetRasterizerCaps(&rsSafe)) 196 { 197 _SEH2_TRY 198 { 199 ProbeForWrite( praststat, 200 sizeof(RASTERIZER_STATUS), 201 1); 202 RtlCopyMemory(praststat, &rsSafe, cjBytes ); 203 } 204 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 205 { 206 Status = _SEH2_GetExceptionCode(); 207 } 208 _SEH2_END; 209 210 if (!NT_SUCCESS(Status)) 211 { 212 SetLastNtError(Status); 213 return FALSE; 214 } 215 216 return TRUE; 217 } 218 } 219 return FALSE; 220 } 221 222 INT 223 APIENTRY 224 NtGdiGetTextCharsetInfo( 225 IN HDC hdc, 226 OUT OPTIONAL LPFONTSIGNATURE lpSig, 227 IN DWORD dwFlags) 228 { 229 PDC Dc; 230 INT Ret; 231 FONTSIGNATURE fsSafe; 232 PFONTSIGNATURE pfsSafe = &fsSafe; 233 NTSTATUS Status = STATUS_SUCCESS; 234 235 Dc = DC_LockDc(hdc); 236 if (!Dc) 237 { 238 EngSetLastError(ERROR_INVALID_HANDLE); 239 return DEFAULT_CHARSET; 240 } 241 242 if (!lpSig) pfsSafe = NULL; 243 244 Ret = HIWORD(ftGdiGetTextCharsetInfo( Dc, pfsSafe, dwFlags)); 245 246 if (lpSig) 247 { 248 if (Ret == DEFAULT_CHARSET) 249 RtlZeroMemory(pfsSafe, sizeof(FONTSIGNATURE)); 250 251 _SEH2_TRY 252 { 253 ProbeForWrite( lpSig, 254 sizeof(FONTSIGNATURE), 255 1); 256 RtlCopyMemory(lpSig, pfsSafe, sizeof(FONTSIGNATURE)); 257 } 258 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 259 { 260 Status = _SEH2_GetExceptionCode(); 261 } 262 _SEH2_END; 263 264 if (!NT_SUCCESS(Status)) 265 { 266 SetLastNtError(Status); 267 return DEFAULT_CHARSET; 268 } 269 } 270 DC_UnlockDc(Dc); 271 return Ret; 272 } 273 274 275 /* 276 fl : 277 GetTextExtentExPointW = 0 and everything else that uses this. 278 GetTextExtentExPointI = 1 279 */ 280 W32KAPI 281 BOOL 282 APIENTRY 283 NtGdiGetTextExtentExW( 284 IN HDC hDC, 285 IN OPTIONAL LPWSTR UnsafeString, 286 IN ULONG Count, 287 IN ULONG MaxExtent, 288 OUT OPTIONAL PULONG UnsafeFit, 289 OUT OPTIONAL PULONG UnsafeDx, 290 OUT LPSIZE UnsafeSize, 291 IN FLONG fl 292 ) 293 { 294 PDC dc; 295 PDC_ATTR pdcattr; 296 LPWSTR String; 297 SIZE Size; 298 NTSTATUS Status; 299 BOOLEAN Result; 300 INT Fit; 301 LPINT Dx; 302 PTEXTOBJ TextObj; 303 304 if ((LONG)Count < 0) 305 { 306 EngSetLastError(ERROR_INVALID_PARAMETER); 307 return FALSE; 308 } 309 310 /* FIXME: Handle fl */ 311 312 if (0 == Count) 313 { 314 Size.cx = 0; 315 Size.cy = 0; 316 Status = MmCopyToCaller(UnsafeSize, &Size, sizeof(SIZE)); 317 if (! NT_SUCCESS(Status)) 318 { 319 SetLastNtError(Status); 320 return FALSE; 321 } 322 return TRUE; 323 } 324 325 String = ExAllocatePoolWithTag(PagedPool, Count * sizeof(WCHAR), GDITAG_TEXT); 326 if (NULL == String) 327 { 328 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); 329 return FALSE; 330 } 331 332 if (NULL != UnsafeDx) 333 { 334 Dx = ExAllocatePoolWithTag(PagedPool, Count * sizeof(INT), GDITAG_TEXT); 335 if (NULL == Dx) 336 { 337 ExFreePoolWithTag(String, GDITAG_TEXT); 338 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); 339 return FALSE; 340 } 341 } 342 else 343 { 344 Dx = NULL; 345 } 346 347 Status = MmCopyFromCaller(String, UnsafeString, Count * sizeof(WCHAR)); 348 if (! NT_SUCCESS(Status)) 349 { 350 if (NULL != Dx) 351 { 352 ExFreePoolWithTag(Dx, GDITAG_TEXT); 353 } 354 ExFreePoolWithTag(String, GDITAG_TEXT); 355 SetLastNtError(Status); 356 return FALSE; 357 } 358 359 dc = DC_LockDc(hDC); 360 if (NULL == dc) 361 { 362 if (NULL != Dx) 363 { 364 ExFreePoolWithTag(Dx, GDITAG_TEXT); 365 } 366 ExFreePoolWithTag(String, GDITAG_TEXT); 367 EngSetLastError(ERROR_INVALID_HANDLE); 368 return FALSE; 369 } 370 pdcattr = dc->pdcattr; 371 TextObj = RealizeFontInit(pdcattr->hlfntNew); 372 if ( TextObj ) 373 { 374 Result = TextIntGetTextExtentPoint( dc, 375 TextObj, 376 String, 377 Count, 378 MaxExtent, 379 NULL == UnsafeFit ? NULL : &Fit, 380 Dx, 381 &Size, 382 fl); 383 TEXTOBJ_UnlockText(TextObj); 384 } 385 else 386 Result = FALSE; 387 DC_UnlockDc(dc); 388 389 ExFreePoolWithTag(String, GDITAG_TEXT); 390 if (! Result) 391 { 392 if (NULL != Dx) 393 { 394 ExFreePoolWithTag(Dx, GDITAG_TEXT); 395 } 396 return FALSE; 397 } 398 399 if (NULL != UnsafeFit) 400 { 401 Status = MmCopyToCaller(UnsafeFit, &Fit, sizeof(INT)); 402 if (! NT_SUCCESS(Status)) 403 { 404 if (NULL != Dx) 405 { 406 ExFreePoolWithTag(Dx, GDITAG_TEXT); 407 } 408 SetLastNtError(Status); 409 return FALSE; 410 } 411 } 412 413 if (NULL != UnsafeDx) 414 { 415 Status = MmCopyToCaller(UnsafeDx, Dx, Count * sizeof(INT)); 416 if (! NT_SUCCESS(Status)) 417 { 418 if (NULL != Dx) 419 { 420 ExFreePoolWithTag(Dx, GDITAG_TEXT); 421 } 422 SetLastNtError(Status); 423 return FALSE; 424 } 425 } 426 if (NULL != Dx) 427 { 428 ExFreePoolWithTag(Dx, GDITAG_TEXT); 429 } 430 431 Status = MmCopyToCaller(UnsafeSize, &Size, sizeof(SIZE)); 432 if (! NT_SUCCESS(Status)) 433 { 434 SetLastNtError(Status); 435 return FALSE; 436 } 437 438 return TRUE; 439 } 440 441 442 /* 443 flOpts : 444 GetTextExtentPoint32W = 0 445 GetTextExtentPointW = 1 446 */ 447 BOOL 448 APIENTRY 449 NtGdiGetTextExtent(HDC hdc, 450 LPWSTR lpwsz, 451 INT cwc, 452 LPSIZE psize, 453 UINT flOpts) 454 { 455 return NtGdiGetTextExtentExW(hdc, lpwsz, cwc, 0, NULL, NULL, psize, flOpts); 456 } 457 458 BOOL 459 APIENTRY 460 NtGdiSetTextJustification(HDC hDC, 461 int BreakExtra, 462 int BreakCount) 463 { 464 PDC pDc; 465 PDC_ATTR pdcattr; 466 467 pDc = DC_LockDc(hDC); 468 if (!pDc) 469 { 470 EngSetLastError(ERROR_INVALID_HANDLE); 471 return FALSE; 472 } 473 474 pdcattr = pDc->pdcattr; 475 476 pdcattr->lBreakExtra = BreakExtra; 477 pdcattr->cBreak = BreakCount; 478 479 DC_UnlockDc(pDc); 480 return TRUE; 481 } 482 483 484 W32KAPI 485 INT 486 APIENTRY 487 NtGdiGetTextFaceW( 488 IN HDC hDC, 489 IN INT Count, 490 OUT OPTIONAL LPWSTR FaceName, 491 IN BOOL bAliasName 492 ) 493 { 494 PDC Dc; 495 PDC_ATTR pdcattr; 496 HFONT hFont; 497 PTEXTOBJ TextObj; 498 NTSTATUS Status; 499 SIZE_T fLen; 500 INT ret; 501 502 /* FIXME: Handle bAliasName */ 503 504 Dc = DC_LockDc(hDC); 505 if (Dc == NULL) 506 { 507 EngSetLastError(ERROR_INVALID_HANDLE); 508 return FALSE; 509 } 510 pdcattr = Dc->pdcattr; 511 hFont = pdcattr->hlfntNew; 512 DC_UnlockDc(Dc); 513 514 TextObj = RealizeFontInit(hFont); 515 ASSERT(TextObj != NULL); 516 fLen = wcslen(TextObj->TextFace) + 1; 517 518 if (FaceName != NULL) 519 { 520 Count = min(Count, fLen); 521 Status = MmCopyToCaller(FaceName, TextObj->TextFace, Count * sizeof(WCHAR)); 522 if (!NT_SUCCESS(Status)) 523 { 524 TEXTOBJ_UnlockText(TextObj); 525 SetLastNtError(Status); 526 return 0; 527 } 528 /* Terminate if we copied only part of the font name */ 529 if (Count > 0 && Count < fLen) 530 { 531 FaceName[Count - 1] = '\0'; 532 } 533 ret = Count; 534 } 535 else 536 { 537 ret = fLen; 538 } 539 540 TEXTOBJ_UnlockText(TextObj); 541 return ret; 542 } 543 544 W32KAPI 545 BOOL 546 APIENTRY 547 NtGdiGetTextMetricsW( 548 IN HDC hDC, 549 OUT TMW_INTERNAL * pUnsafeTmwi, 550 IN ULONG cj) 551 { 552 TMW_INTERNAL Tmwi; 553 554 if ( cj <= sizeof(TMW_INTERNAL) ) 555 { 556 if (ftGdiGetTextMetricsW(hDC, &Tmwi)) 557 { 558 _SEH2_TRY 559 { 560 ProbeForWrite(pUnsafeTmwi, cj, 1); 561 RtlCopyMemory(pUnsafeTmwi, &Tmwi, cj); 562 } 563 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 564 { 565 SetLastNtError(_SEH2_GetExceptionCode()); 566 _SEH2_YIELD(return FALSE); 567 } 568 _SEH2_END 569 570 return TRUE; 571 } 572 } 573 return FALSE; 574 } 575 576 /* EOF */ 577