f1c7a1c4cd20974faf3c38a052982a270e180307
[reactos.git] / reactos / subsystems / win32 / win32k / objects / font.c
1 /*
2 * PROJECT: ReactOS win32 kernel mode subsystem
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: subsystems/win32/win32k/objects/font.c
5 * PURPOSE: Font
6 * PROGRAMMER:
7 */
8
9 /** Includes ******************************************************************/
10
11 #include <w32k.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 /** Internal ******************************************************************/
17
18 INT
19 FASTCALL
20 FontGetObject(PTEXTOBJ TFont, INT Count, PVOID Buffer)
21 {
22 if( Buffer == NULL ) return sizeof(LOGFONTW);
23
24 switch (Count)
25 {
26 case sizeof(ENUMLOGFONTEXDVW):
27 RtlCopyMemory( (LPENUMLOGFONTEXDVW) Buffer,
28 &TFont->logfont,
29 sizeof(ENUMLOGFONTEXDVW));
30 break;
31 case sizeof(ENUMLOGFONTEXW):
32 RtlCopyMemory( (LPENUMLOGFONTEXW) Buffer,
33 &TFont->logfont.elfEnumLogfontEx,
34 sizeof(ENUMLOGFONTEXW));
35 break;
36
37 case sizeof(EXTLOGFONTW):
38 case sizeof(ENUMLOGFONTW):
39 RtlCopyMemory((LPENUMLOGFONTW) Buffer,
40 &TFont->logfont.elfEnumLogfontEx.elfLogFont,
41 sizeof(ENUMLOGFONTW));
42 break;
43
44 case sizeof(LOGFONTW):
45 RtlCopyMemory((LPLOGFONTW) Buffer,
46 &TFont->logfont.elfEnumLogfontEx.elfLogFont,
47 sizeof(LOGFONTW));
48 break;
49
50 default:
51 SetLastWin32Error(ERROR_BUFFER_OVERFLOW);
52 return 0;
53 }
54 return Count;
55 }
56
57 DWORD
58 FASTCALL
59 IntGetFontLanguageInfo(PDC Dc)
60 {
61 PDC_ATTR Dc_Attr;
62 FONTSIGNATURE fontsig;
63 static const DWORD GCP_DBCS_MASK=0x003F0000,
64 GCP_DIACRITIC_MASK=0x00000000,
65 FLI_GLYPHS_MASK=0x00000000,
66 GCP_GLYPHSHAPE_MASK=0x00000040,
67 GCP_KASHIDA_MASK=0x00000000,
68 GCP_LIGATE_MASK=0x00000000,
69 GCP_USEKERNING_MASK=0x00000000,
70 GCP_REORDER_MASK=0x00000060;
71
72 DWORD result=0;
73
74 ftGdiGetTextCharsetInfo( Dc, &fontsig, 0 );
75
76 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
77 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
78 result|=GCP_DBCS;
79
80 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
81 result|=GCP_DIACRITIC;
82
83 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
84 result|=FLI_GLYPHS;
85
86 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
87 result|=GCP_GLYPHSHAPE;
88
89 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
90 result|=GCP_KASHIDA;
91
92 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
93 result|=GCP_LIGATE;
94
95 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
96 result|=GCP_USEKERNING;
97
98 Dc_Attr = Dc->pDc_Attr;
99 if(!Dc_Attr) Dc_Attr = &Dc->Dc_Attr;
100
101 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
102 if ( Dc_Attr->lTextAlign & TA_RTLREADING )
103 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
104 result|=GCP_REORDER;
105
106 return result;
107 }
108
109 PTEXTOBJ
110 FASTCALL
111 RealizeFontInit(HFONT hFont)
112 {
113 NTSTATUS Status = STATUS_SUCCESS;
114 PTEXTOBJ pTextObj;
115
116 pTextObj = TEXTOBJ_LockText(hFont);
117
118 if ( pTextObj && !(pTextObj->fl & TEXTOBJECT_INIT))
119 {
120 Status = TextIntRealizeFont(hFont, pTextObj);
121 if (!NT_SUCCESS(Status))
122 {
123 TEXTOBJ_UnlockText(pTextObj);
124 return NULL;
125 }
126 }
127 return pTextObj;
128 }
129
130 /** Functions ******************************************************************/
131
132 INT
133 APIENTRY
134 NtGdiAddFontResourceW(
135 IN WCHAR *pwszFiles,
136 IN ULONG cwc,
137 IN ULONG cFiles,
138 IN FLONG fl,
139 IN DWORD dwPidTid,
140 IN OPTIONAL DESIGNVECTOR *pdv)
141 {
142 UNICODE_STRING SafeFileName;
143 PWSTR src;
144 NTSTATUS Status;
145 int Ret;
146
147 /* FIXME - Protect with SEH? */
148 RtlInitUnicodeString(&SafeFileName, pwszFiles);
149
150 /* Reserve for prepending '\??\' */
151 SafeFileName.Length += 4 * sizeof(WCHAR);
152 SafeFileName.MaximumLength += 4 * sizeof(WCHAR);
153
154 src = SafeFileName.Buffer;
155 SafeFileName.Buffer = (PWSTR)ExAllocatePoolWithTag(PagedPool, SafeFileName.MaximumLength, TAG_STRING);
156 if(!SafeFileName.Buffer)
157 {
158 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
159 return 0;
160 }
161
162 /* Prepend '\??\' */
163 RtlCopyMemory(SafeFileName.Buffer, L"\\??\\", 4 * sizeof(WCHAR));
164
165 Status = MmCopyFromCaller(SafeFileName.Buffer + 4, src, SafeFileName.MaximumLength - (4 * sizeof(WCHAR)));
166 if(!NT_SUCCESS(Status))
167 {
168 ExFreePoolWithTag(SafeFileName.Buffer, TAG_STRING);
169 SetLastNtError(Status);
170 return 0;
171 }
172
173 Ret = IntGdiAddFontResource(&SafeFileName, (DWORD)fl);
174
175 ExFreePoolWithTag(SafeFileName.Buffer, TAG_STRING);
176 return Ret;
177 }
178
179 DWORD
180 APIENTRY
181 NtGdiGetFontData(
182 HDC hDC,
183 DWORD Table,
184 DWORD Offset,
185 LPVOID Buffer,
186 DWORD Size)
187 {
188 PDC Dc;
189 PDC_ATTR Dc_Attr;
190 HFONT hFont;
191 PTEXTOBJ TextObj;
192 PFONTGDI FontGdi;
193 DWORD Result = GDI_ERROR;
194 NTSTATUS Status = STATUS_SUCCESS;
195
196 if (Buffer && Size)
197 {
198 _SEH2_TRY
199 {
200 ProbeForRead(Buffer, Size, 1);
201 }
202 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
203 {
204 Status = _SEH2_GetExceptionCode();
205 }
206 _SEH2_END
207 }
208
209 if (!NT_SUCCESS(Status)) return Result;
210
211 Dc = DC_LockDc(hDC);
212 if (Dc == NULL)
213 {
214 SetLastWin32Error(ERROR_INVALID_HANDLE);
215 return GDI_ERROR;
216 }
217 Dc_Attr = Dc->pDc_Attr;
218 if(!Dc_Attr) Dc_Attr = &Dc->Dc_Attr;
219
220 hFont = Dc_Attr->hlfntNew;
221 TextObj = RealizeFontInit(hFont);
222 DC_UnlockDc(Dc);
223
224 if (TextObj == NULL)
225 {
226 SetLastWin32Error(ERROR_INVALID_HANDLE);
227 return GDI_ERROR;
228 }
229
230 FontGdi = ObjToGDI(TextObj->Font, FONT);
231
232 Result = ftGdiGetFontData(FontGdi, Table, Offset, Buffer, Size);
233
234 TEXTOBJ_UnlockText(TextObj);
235
236 return Result;
237 }
238
239 /*
240 * @implemented
241 */
242 DWORD
243 APIENTRY
244 NtGdiGetFontUnicodeRanges(
245 IN HDC hdc,
246 OUT OPTIONAL LPGLYPHSET pgs)
247 {
248 PDC pDc;
249 PDC_ATTR Dc_Attr;
250 HFONT hFont;
251 PTEXTOBJ TextObj;
252 PFONTGDI FontGdi;
253 DWORD Size = 0;
254 PGLYPHSET pgsSafe;
255 NTSTATUS Status = STATUS_SUCCESS;
256
257 pDc = DC_LockDc(hdc);
258 if (!pDc)
259 {
260 SetLastWin32Error(ERROR_INVALID_HANDLE);
261 return 0;
262 }
263
264 Dc_Attr = pDc->pDc_Attr;
265 if(!Dc_Attr) Dc_Attr = &pDc->Dc_Attr;
266
267 hFont = Dc_Attr->hlfntNew;
268 TextObj = RealizeFontInit(hFont);
269
270 if ( TextObj == NULL)
271 {
272 SetLastWin32Error(ERROR_INVALID_HANDLE);
273 goto Exit;
274 }
275 FontGdi = ObjToGDI(TextObj->Font, FONT);
276
277 Size = ftGetFontUnicodeRanges( FontGdi, NULL);
278
279 if (Size && pgs)
280 {
281 pgsSafe = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT);
282 if (!pgsSafe)
283 {
284 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
285 Size = 0;
286 goto Exit;
287 }
288
289 Size = ftGetFontUnicodeRanges( FontGdi, pgsSafe);
290
291 if (Size)
292 {
293 _SEH2_TRY
294 {
295 ProbeForWrite(pgs, Size, 1);
296 RtlCopyMemory(pgs, pgsSafe, Size);
297 }
298 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
299 {
300 Status = _SEH2_GetExceptionCode();
301 }
302 _SEH2_END
303
304 if (!NT_SUCCESS(Status)) Size = 0;
305 }
306 ExFreePoolWithTag(pgsSafe, TAG_GDITEXT);
307 }
308 Exit:
309 TEXTOBJ_UnlockText(TextObj);
310 DC_UnlockDc(pDc);
311 return Size;
312 }
313
314 ULONG
315 APIENTRY
316 NtGdiGetGlyphOutline(
317 IN HDC hdc,
318 IN WCHAR wch,
319 IN UINT iFormat,
320 OUT LPGLYPHMETRICS pgm,
321 IN ULONG cjBuf,
322 OUT OPTIONAL PVOID UnsafeBuf,
323 IN LPMAT2 pmat2,
324 IN BOOL bIgnoreRotation)
325 {
326 ULONG Ret = GDI_ERROR;
327 PDC dc;
328 PVOID pvBuf = NULL;
329 GLYPHMETRICS gm;
330 NTSTATUS Status = STATUS_SUCCESS;
331
332 dc = DC_LockDc(hdc);
333 if (!dc)
334 {
335 SetLastWin32Error(ERROR_INVALID_HANDLE);
336 return GDI_ERROR;
337 }
338
339 if (UnsafeBuf && cjBuf)
340 {
341 pvBuf = ExAllocatePoolWithTag(PagedPool, cjBuf, TAG_GDITEXT);
342 if (!pvBuf)
343 {
344 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
345 goto Exit;
346 }
347 }
348
349 Ret = ftGdiGetGlyphOutline( dc,
350 wch,
351 iFormat,
352 pgm ? &gm : NULL,
353 cjBuf,
354 pvBuf,
355 pmat2,
356 bIgnoreRotation);
357
358 if (pvBuf)
359 {
360 _SEH2_TRY
361 {
362 ProbeForWrite(UnsafeBuf, cjBuf, 1);
363 RtlCopyMemory(UnsafeBuf, pvBuf, cjBuf);
364 }
365 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
366 {
367 Status = _SEH2_GetExceptionCode();
368 }
369 _SEH2_END
370
371 ExFreePoolWithTag(pvBuf, TAG_GDITEXT);
372 }
373
374 if (pgm)
375 {
376 _SEH2_TRY
377 {
378 ProbeForWrite(pgm, sizeof(GLYPHMETRICS), 1);
379 RtlCopyMemory(pgm, &gm, sizeof(GLYPHMETRICS));
380 }
381 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
382 {
383 Status = _SEH2_GetExceptionCode();
384 }
385 _SEH2_END
386 }
387
388 if (! NT_SUCCESS(Status))
389 {
390 SetLastWin32Error(ERROR_INVALID_PARAMETER);
391 Ret = GDI_ERROR;
392 }
393
394 Exit:
395 DC_UnlockDc(dc);
396 return Ret;
397 }
398
399 DWORD
400 APIENTRY
401 NtGdiGetKerningPairs(HDC hDC,
402 ULONG NumPairs,
403 LPKERNINGPAIR krnpair)
404 {
405 PDC dc;
406 PDC_ATTR Dc_Attr;
407 PTEXTOBJ TextObj;
408 PFONTGDI FontGDI;
409 DWORD Count;
410 KERNINGPAIR *pKP;
411 NTSTATUS Status = STATUS_SUCCESS;
412
413 dc = DC_LockDc(hDC);
414 if (!dc)
415 {
416 SetLastWin32Error(ERROR_INVALID_HANDLE);
417 return 0;
418 }
419
420 Dc_Attr = dc->pDc_Attr;
421 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
422 TextObj = RealizeFontInit(Dc_Attr->hlfntNew);
423 DC_UnlockDc(dc);
424
425 if (!TextObj)
426 {
427 SetLastWin32Error(ERROR_INVALID_HANDLE);
428 return 0;
429 }
430
431 FontGDI = ObjToGDI(TextObj->Font, FONT);
432 TEXTOBJ_UnlockText(TextObj);
433
434 Count = ftGdiGetKerningPairs(FontGDI,0,NULL);
435
436 if ( Count && krnpair )
437 {
438 if (Count > NumPairs)
439 {
440 SetLastWin32Error(ERROR_INSUFFICIENT_BUFFER);
441 return 0;
442 }
443 pKP = ExAllocatePoolWithTag(PagedPool, Count * sizeof(KERNINGPAIR), TAG_GDITEXT);
444 if (!pKP)
445 {
446 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
447 return 0;
448 }
449 ftGdiGetKerningPairs(FontGDI,Count,pKP);
450 _SEH2_TRY
451 {
452 ProbeForWrite(krnpair, Count * sizeof(KERNINGPAIR), 1);
453 RtlCopyMemory(krnpair, pKP, Count * sizeof(KERNINGPAIR));
454 }
455 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
456 {
457 Status = _SEH2_GetExceptionCode();
458 }
459 _SEH2_END
460 if (!NT_SUCCESS(Status))
461 {
462 SetLastWin32Error(ERROR_INVALID_PARAMETER);
463 Count = 0;
464 }
465 ExFreePoolWithTag(pKP,TAG_GDITEXT);
466 }
467 return Count;
468 }
469
470 /*
471 From "Undocumented Windows 2000 Secrets" Appendix B, Table B-2, page
472 472, this is NtGdiGetOutlineTextMetricsInternalW.
473 */
474 ULONG
475 APIENTRY
476 NtGdiGetOutlineTextMetricsInternalW (HDC hDC,
477 ULONG Data,
478 OUTLINETEXTMETRICW *otm,
479 TMDIFF *Tmd)
480 {
481 PDC dc;
482 PDC_ATTR Dc_Attr;
483 PTEXTOBJ TextObj;
484 PFONTGDI FontGDI;
485 HFONT hFont = 0;
486 ULONG Size;
487 OUTLINETEXTMETRICW *potm;
488 NTSTATUS Status = STATUS_SUCCESS;
489
490 dc = DC_LockDc(hDC);
491 if (!dc)
492 {
493 SetLastWin32Error(ERROR_INVALID_HANDLE);
494 return 0;
495 }
496 Dc_Attr = dc->pDc_Attr;
497 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
498 hFont = Dc_Attr->hlfntNew;
499 TextObj = RealizeFontInit(hFont);
500 DC_UnlockDc(dc);
501 if (!TextObj)
502 {
503 SetLastWin32Error(ERROR_INVALID_HANDLE);
504 return 0;
505 }
506 FontGDI = ObjToGDI(TextObj->Font, FONT);
507 TEXTOBJ_UnlockText(TextObj);
508 Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
509 if (!otm) return Size;
510 if (Size > Data)
511 {
512 SetLastWin32Error(ERROR_INSUFFICIENT_BUFFER);
513 return 0;
514 }
515 potm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT);
516 if (!potm)
517 {
518 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
519 return 0;
520 }
521 IntGetOutlineTextMetrics(FontGDI, Size, potm);
522 if (otm)
523 {
524 _SEH2_TRY
525 {
526 ProbeForWrite(otm, Size, 1);
527 RtlCopyMemory(otm, potm, Size);
528 }
529 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
530 {
531 Status = _SEH2_GetExceptionCode();
532 }
533 _SEH2_END
534
535 if (!NT_SUCCESS(Status))
536 {
537 SetLastWin32Error(ERROR_INVALID_PARAMETER);
538 Size = 0;
539 }
540 }
541 ExFreePoolWithTag(potm,TAG_GDITEXT);
542 return Size;
543 }
544
545 W32KAPI
546 BOOL
547 APIENTRY
548 NtGdiGetFontResourceInfoInternalW(
549 IN LPWSTR pwszFiles,
550 IN ULONG cwc,
551 IN ULONG cFiles,
552 IN UINT cjIn,
553 OUT LPDWORD pdwBytes,
554 OUT LPVOID pvBuf,
555 IN DWORD dwType)
556 {
557 NTSTATUS Status = STATUS_SUCCESS;
558 DWORD dwBytes;
559 UNICODE_STRING SafeFileNames;
560 BOOL bRet = FALSE;
561 ULONG cbStringSize;
562
563 union
564 {
565 LOGFONTW logfontw;
566 WCHAR FullName[LF_FULLFACESIZE];
567 } Buffer;
568
569 /* FIXME: handle cFiles > 0 */
570
571 /* Check for valid dwType values
572 dwType == 4 seems to be handled by gdi32 only */
573 if (dwType == 4 || dwType > 5)
574 {
575 SetLastWin32Error(ERROR_INVALID_PARAMETER);
576 return FALSE;
577 }
578
579 /* Allocate a safe unicode string buffer */
580 cbStringSize = cwc * sizeof(WCHAR);
581 SafeFileNames.MaximumLength = SafeFileNames.Length = cbStringSize - sizeof(WCHAR);
582 SafeFileNames.Buffer = ExAllocatePoolWithTag(PagedPool,
583 cbStringSize,
584 TAG('R','T','S','U'));
585 if (!SafeFileNames.Buffer)
586 {
587 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
588 return FALSE;
589 }
590
591 /* Check buffers and copy pwszFiles to safe unicode string */
592 _SEH2_TRY
593 {
594 ProbeForRead(pwszFiles, cbStringSize, 1);
595 ProbeForWrite(pdwBytes, sizeof(DWORD), 1);
596 ProbeForWrite(pvBuf, cjIn, 1);
597
598 RtlCopyMemory(SafeFileNames.Buffer, pwszFiles, cbStringSize);
599 }
600 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
601 {
602 Status = _SEH2_GetExceptionCode();
603 }
604 _SEH2_END
605
606 if(!NT_SUCCESS(Status))
607 {
608 SetLastNtError(Status);
609 /* Free the string buffer for the safe filename */
610 ExFreePoolWithTag(SafeFileNames.Buffer,TAG('R','T','S','U'));
611 return FALSE;
612 }
613
614 /* Do the actual call */
615 bRet = IntGdiGetFontResourceInfo(&SafeFileNames, &Buffer, &dwBytes, dwType);
616
617 /* Check if succeeded and the buffer is big enough */
618 if (bRet && cjIn >= dwBytes)
619 {
620 /* Copy the data back to caller */
621 _SEH2_TRY
622 {
623 /* Buffers are already probed */
624 RtlCopyMemory(pvBuf, &Buffer, dwBytes);
625 *pdwBytes = dwBytes;
626 }
627 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
628 {
629 Status = _SEH2_GetExceptionCode();
630 }
631 _SEH2_END
632
633 if(!NT_SUCCESS(Status))
634 {
635 SetLastNtError(Status);
636 bRet = FALSE;
637 }
638 }
639
640 /* Free the string for the safe filenames */
641 ExFreePoolWithTag(SafeFileNames.Buffer,TAG('R','T','S','U'));
642
643 return bRet;
644 }
645
646 /*
647 * @unimplemented
648 */
649 BOOL
650 APIENTRY
651 NtGdiGetRealizationInfo(
652 IN HDC hdc,
653 OUT PREALIZATION_INFO pri,
654 IN HFONT hf)
655 {
656 PDC pDc;
657 PTEXTOBJ pTextObj;
658 PFONTGDI pFontGdi;
659 PDC_ATTR Dc_Attr;
660 BOOL Ret = FALSE;
661 INT i = 0;
662 REALIZATION_INFO ri;
663
664 pDc = DC_LockDc(hdc);
665 if (!pDc)
666 {
667 SetLastWin32Error(ERROR_INVALID_HANDLE);
668 return 0;
669 }
670 Dc_Attr = pDc->pDc_Attr;
671 if(!Dc_Attr) Dc_Attr = &pDc->Dc_Attr;
672 pTextObj = RealizeFontInit(Dc_Attr->hlfntNew);
673 pFontGdi = ObjToGDI(pTextObj->Font, FONT);
674 TEXTOBJ_UnlockText(pTextObj);
675 DC_UnlockDc(pDc);
676
677 Ret = ftGdiRealizationInfo(pFontGdi, &ri);
678 if (Ret)
679 {
680 if (pri)
681 {
682 NTSTATUS Status = STATUS_SUCCESS;
683 _SEH2_TRY
684 {
685 ProbeForWrite(pri, sizeof(REALIZATION_INFO), 1);
686 RtlCopyMemory(pri, &ri, sizeof(REALIZATION_INFO));
687 }
688 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
689 {
690 Status = _SEH2_GetExceptionCode();
691 }
692 _SEH2_END
693
694 if(!NT_SUCCESS(Status))
695 {
696 SetLastNtError(Status);
697 return FALSE;
698 }
699 }
700 do
701 {
702 if (GdiHandleTable->cfPublic[i].hf == hf)
703 {
704 GdiHandleTable->cfPublic[i].iTechnology = ri.iTechnology;
705 GdiHandleTable->cfPublic[i].iUniq = ri.iUniq;
706 GdiHandleTable->cfPublic[i].dwUnknown = ri.dwUnknown;
707 GdiHandleTable->cfPublic[i].dwCFCount = GdiHandleTable->dwCFCount;
708 GdiHandleTable->cfPublic[i].fl |= CFONT_REALIZATION;
709 }
710 i++;
711 }
712 while ( i < GDI_CFONT_MAX );
713 }
714 return Ret;
715 }
716
717 HFONT
718 APIENTRY
719 NtGdiHfontCreate(
720 IN PENUMLOGFONTEXDVW pelfw,
721 IN ULONG cjElfw,
722 IN LFTYPE lft,
723 IN FLONG fl,
724 IN PVOID pvCliData )
725 {
726 ENUMLOGFONTEXDVW SafeLogfont;
727 HFONT hNewFont;
728 PTEXTOBJ TextObj;
729 NTSTATUS Status = STATUS_SUCCESS;
730
731 if (!pelfw)
732 {
733 return NULL;
734 }
735
736 _SEH2_TRY
737 {
738 ProbeForRead(pelfw, sizeof(ENUMLOGFONTEXDVW), 1);
739 RtlCopyMemory(&SafeLogfont, pelfw, sizeof(ENUMLOGFONTEXDVW));
740 }
741 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
742 {
743 Status = _SEH2_GetExceptionCode();
744 }
745 _SEH2_END
746
747 if (!NT_SUCCESS(Status))
748 {
749 return NULL;
750 }
751
752 TextObj = TEXTOBJ_AllocTextWithHandle();
753 if (!TextObj)
754 {
755 return NULL;
756 }
757 hNewFont = TextObj->BaseObject.hHmgr;
758
759 TextObj->lft = lft;
760 TextObj->fl = fl;
761 RtlCopyMemory (&TextObj->logfont, &SafeLogfont, sizeof(ENUMLOGFONTEXDVW));
762
763 if (SafeLogfont.elfEnumLogfontEx.elfLogFont.lfEscapement !=
764 SafeLogfont.elfEnumLogfontEx.elfLogFont.lfOrientation)
765 {
766 /* this should really depend on whether GM_ADVANCED is set */
767 TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfOrientation =
768 TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfEscapement;
769 }
770 TEXTOBJ_UnlockText(TextObj);
771
772 return hNewFont;
773 }
774
775 /*
776 * @implemented
777 */
778 HFONT
779 APIENTRY
780 NtGdiSelectFont(
781 IN HDC hDC,
782 IN HFONT hFont)
783 {
784 PDC pDC;
785 PDC_ATTR pDc_Attr;
786 HFONT hOrgFont = NULL;
787
788 if (hDC == NULL || hFont == NULL) return NULL;
789
790 pDC = DC_LockDc(hDC);
791 if (!pDC)
792 {
793 return NULL;
794 }
795
796 pDc_Attr = pDC->pDc_Attr;
797 if(!pDc_Attr) pDc_Attr = &pDC->Dc_Attr;
798
799 /* FIXME: what if not successful? */
800 if(NT_SUCCESS(TextIntRealizeFont((HFONT)hFont,NULL)))
801 {
802 hOrgFont = pDc_Attr->hlfntNew;
803 pDc_Attr->hlfntNew = hFont;
804 }
805
806 DC_UnlockDc(pDC);
807
808 return hOrgFont;
809 }
810
811
812 /* EOF */