Fix spurious warning/error reported by GCC 4.4.0.
[reactos.git] / reactos / subsystems / win32 / win32k / objects / font.c
index 27d9651..1f49571 100644 (file)
 #define NDEBUG
 #include <debug.h>
 
+/** Internal ******************************************************************/
+
+INT
+FASTCALL
+FontGetObject(PTEXTOBJ TFont, INT Count, PVOID Buffer)
+{
+  if( Buffer == NULL ) return sizeof(LOGFONTW);
+
+  switch (Count)
+  {
+     case sizeof(ENUMLOGFONTEXDVW):
+        RtlCopyMemory( (LPENUMLOGFONTEXDVW) Buffer,
+                                            &TFont->logfont,
+                                            sizeof(ENUMLOGFONTEXDVW));
+        break;
+     case sizeof(ENUMLOGFONTEXW):
+        RtlCopyMemory( (LPENUMLOGFONTEXW) Buffer,
+                                          &TFont->logfont.elfEnumLogfontEx,
+                                          sizeof(ENUMLOGFONTEXW));
+        break;
+
+     case sizeof(EXTLOGFONTW):
+     case sizeof(ENUMLOGFONTW):
+        RtlCopyMemory((LPENUMLOGFONTW) Buffer,
+                                    &TFont->logfont.elfEnumLogfontEx.elfLogFont,
+                                       sizeof(ENUMLOGFONTW));
+        break;
+
+     case sizeof(LOGFONTW):
+        RtlCopyMemory((LPLOGFONTW) Buffer,
+                                   &TFont->logfont.elfEnumLogfontEx.elfLogFont,
+                                   sizeof(LOGFONTW));
+        break;
+
+     default:
+        SetLastWin32Error(ERROR_BUFFER_OVERFLOW);
+        return 0;
+  }
+  return Count;
+}
+
+DWORD
+FASTCALL
+IntGetFontLanguageInfo(PDC Dc)
+{
+  PDC_ATTR Dc_Attr;
+  FONTSIGNATURE fontsig;
+  static const DWORD GCP_DBCS_MASK=0x003F0000,
+               GCP_DIACRITIC_MASK=0x00000000,
+               FLI_GLYPHS_MASK=0x00000000,
+               GCP_GLYPHSHAPE_MASK=0x00000040,
+               GCP_KASHIDA_MASK=0x00000000,
+               GCP_LIGATE_MASK=0x00000000,
+               GCP_USEKERNING_MASK=0x00000000,
+               GCP_REORDER_MASK=0x00000060;
+
+  DWORD result=0;
+
+  ftGdiGetTextCharsetInfo( Dc, &fontsig, 0 );
+
+ /* We detect each flag we return using a bitmask on the Codepage Bitfields */
+  if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
+               result|=GCP_DBCS;
+
+  if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
+               result|=GCP_DIACRITIC;
+
+  if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
+               result|=FLI_GLYPHS;
+
+  if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
+               result|=GCP_GLYPHSHAPE;
+
+  if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
+               result|=GCP_KASHIDA;
+
+  if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
+               result|=GCP_LIGATE;
+
+  if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
+               result|=GCP_USEKERNING;
+
+  Dc_Attr = Dc->pDc_Attr;
+  if(!Dc_Attr) Dc_Attr = &Dc->Dc_Attr;
+
+  /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
+  if ( Dc_Attr->lTextAlign & TA_RTLREADING )
+     if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
+                    result|=GCP_REORDER;
+
+  return result;
+}
+
+PTEXTOBJ
+FASTCALL
+RealizeFontInit(HFONT hFont)
+{
+  NTSTATUS Status = STATUS_SUCCESS;
+  PTEXTOBJ pTextObj;
+
+  pTextObj = TEXTOBJ_LockText(hFont);
+
+  if ( pTextObj && !(pTextObj->fl & TEXTOBJECT_INIT))
+  {
+     Status = TextIntRealizeFont(hFont, pTextObj);
+     if (!NT_SUCCESS(Status))
+     {
+        TEXTOBJ_UnlockText(pTextObj);
+        return NULL;
+     }
+  }
+  return pTextObj;
+}
+
 /** Functions ******************************************************************/
 
 INT
@@ -51,17 +165,152 @@ NtGdiAddFontResourceW(
   Status = MmCopyFromCaller(SafeFileName.Buffer + 4, src, SafeFileName.MaximumLength - (4 * sizeof(WCHAR)));
   if(!NT_SUCCESS(Status))
   {
-    ExFreePool(SafeFileName.Buffer);
+    ExFreePoolWithTag(SafeFileName.Buffer, TAG_STRING);
     SetLastNtError(Status);
     return 0;
   }
 
   Ret = IntGdiAddFontResource(&SafeFileName, (DWORD)fl);
 
-  ExFreePool(SafeFileName.Buffer);
+  ExFreePoolWithTag(SafeFileName.Buffer, TAG_STRING);
   return Ret;
 }
 
+DWORD
+APIENTRY
+NtGdiGetFontData(
+   HDC hDC,
+   DWORD Table,
+   DWORD Offset,
+   LPVOID Buffer,
+   DWORD Size)
+{
+  PDC Dc;
+  PDC_ATTR Dc_Attr;
+  HFONT hFont;
+  PTEXTOBJ TextObj;
+  PFONTGDI FontGdi;
+  DWORD Result = GDI_ERROR;
+  NTSTATUS Status = STATUS_SUCCESS;
+
+  if (Buffer && Size)
+  {
+     _SEH2_TRY
+     {
+         ProbeForRead(Buffer, Size, 1);
+     }
+     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+     {
+         Status = _SEH2_GetExceptionCode();
+     }
+     _SEH2_END
+  }
+
+  if (!NT_SUCCESS(Status)) return Result;
+
+  Dc = DC_LockDc(hDC);
+  if (Dc == NULL)
+  {
+     SetLastWin32Error(ERROR_INVALID_HANDLE);
+     return GDI_ERROR;
+  }
+  Dc_Attr = Dc->pDc_Attr;
+  if(!Dc_Attr) Dc_Attr = &Dc->Dc_Attr;
+
+  hFont = Dc_Attr->hlfntNew;
+  TextObj = RealizeFontInit(hFont);
+  DC_UnlockDc(Dc);
+
+  if (TextObj == NULL)
+  {
+     SetLastWin32Error(ERROR_INVALID_HANDLE);
+     return GDI_ERROR;
+  }
+
+  FontGdi = ObjToGDI(TextObj->Font, FONT);
+
+  Result = ftGdiGetFontData(FontGdi, Table, Offset, Buffer, Size);
+
+  TEXTOBJ_UnlockText(TextObj);
+
+  return Result;
+}
+
+ /*
+ * @implemented
+ */
+DWORD
+APIENTRY
+NtGdiGetFontUnicodeRanges(
+    IN HDC hdc,
+    OUT OPTIONAL LPGLYPHSET pgs)
+{
+  PDC pDc;
+  PDC_ATTR Dc_Attr;
+  HFONT hFont;
+  PTEXTOBJ TextObj;
+  PFONTGDI FontGdi;
+  DWORD Size = 0;
+  PGLYPHSET pgsSafe;
+  NTSTATUS Status = STATUS_SUCCESS;
+
+  pDc = DC_LockDc(hdc);
+  if (!pDc)
+  {
+     SetLastWin32Error(ERROR_INVALID_HANDLE);
+     return 0;
+  }
+
+  Dc_Attr = pDc->pDc_Attr;
+  if(!Dc_Attr) Dc_Attr = &pDc->Dc_Attr;
+
+  hFont = Dc_Attr->hlfntNew;
+  TextObj = RealizeFontInit(hFont);
+        
+  if ( TextObj == NULL)
+  {
+     SetLastWin32Error(ERROR_INVALID_HANDLE);
+     goto Exit;
+  }
+  FontGdi = ObjToGDI(TextObj->Font, FONT);
+
+  Size = ftGetFontUnicodeRanges( FontGdi, NULL);
+
+  if (Size && pgs)
+  {
+     pgsSafe = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT);
+     if (!pgsSafe)
+     {
+        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        Size = 0;
+        goto Exit;
+     }
+
+     Size = ftGetFontUnicodeRanges( FontGdi, pgsSafe);
+
+     if (Size)
+     {     
+        _SEH2_TRY
+        {
+            ProbeForWrite(pgs, Size, 1);
+            RtlCopyMemory(pgs, pgsSafe, Size);
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+           Status = _SEH2_GetExceptionCode();
+        }
+        _SEH2_END
+
+        if (!NT_SUCCESS(Status)) Size = 0;
+     }
+     ExFreePoolWithTag(pgsSafe, TAG_GDITEXT);
+  }
+Exit:
+  TEXTOBJ_UnlockText(TextObj);
+  DC_UnlockDc(pDc);
+  return Size;
+}
+
 ULONG
 APIENTRY
 NtGdiGetGlyphOutline(
@@ -74,34 +323,148 @@ NtGdiGetGlyphOutline(
     IN LPMAT2 pmat2,
     IN BOOL bIgnoreRotation)
 {
-  ULONG Ret;
+  ULONG Ret = GDI_ERROR;
   PDC dc;
+  PVOID pvBuf = NULL;
+  GLYPHMETRICS gm;
+  NTSTATUS Status = STATUS_SUCCESS;
+
   dc = DC_LockDc(hdc);
   if (!dc)
   {
      SetLastWin32Error(ERROR_INVALID_HANDLE);
      return GDI_ERROR;
   }
+
+  if (UnsafeBuf && cjBuf)
+  {
+     pvBuf = ExAllocatePoolWithTag(PagedPool, cjBuf, TAG_GDITEXT);
+     if (!pvBuf)
+     {
+        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        goto Exit;
+     }
+  }
+
   Ret = ftGdiGetGlyphOutline( dc,
                              wch,
                          iFormat,
-                             pgm,
+                             pgm ? &gm : NULL,
                            cjBuf,
-                       UnsafeBuf,
+                           pvBuf,
                            pmat2,
                  bIgnoreRotation);
+
+  if (pvBuf)
+  {
+     _SEH2_TRY
+     {
+         ProbeForWrite(UnsafeBuf, cjBuf, 1);
+         RtlCopyMemory(UnsafeBuf, pvBuf, cjBuf);
+     }
+     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+     {
+         Status = _SEH2_GetExceptionCode();
+     }
+     _SEH2_END
+
+     ExFreePoolWithTag(pvBuf, TAG_GDITEXT);
+  }
+
+  if (pgm)
+  {
+     _SEH2_TRY
+     {
+         ProbeForWrite(pgm, sizeof(GLYPHMETRICS), 1);
+         RtlCopyMemory(pgm, &gm, sizeof(GLYPHMETRICS));
+     }
+     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+     {
+         Status = _SEH2_GetExceptionCode();
+     }
+     _SEH2_END
+  }
+
+  if (! NT_SUCCESS(Status))
+  {
+     SetLastWin32Error(ERROR_INVALID_PARAMETER);
+     Ret = GDI_ERROR;
+  }
+
+Exit:
   DC_UnlockDc(dc);
   return Ret;
 }
 
 DWORD
-STDCALL
+APIENTRY
 NtGdiGetKerningPairs(HDC  hDC,
                      ULONG  NumPairs,
                      LPKERNINGPAIR  krnpair)
 {
-  UNIMPLEMENTED;
-  return 0;
+  PDC dc;
+  PDC_ATTR Dc_Attr;
+  PTEXTOBJ TextObj;
+  PFONTGDI FontGDI;
+  DWORD Count;
+  KERNINGPAIR *pKP;
+  NTSTATUS Status = STATUS_SUCCESS;
+
+  dc = DC_LockDc(hDC);
+  if (!dc)
+  {
+     SetLastWin32Error(ERROR_INVALID_HANDLE);
+     return 0;
+  }
+
+  Dc_Attr = dc->pDc_Attr;
+  if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
+  TextObj = RealizeFontInit(Dc_Attr->hlfntNew);
+  DC_UnlockDc(dc);
+
+  if (!TextObj)
+  {
+     SetLastWin32Error(ERROR_INVALID_HANDLE);
+     return 0;
+  }
+
+  FontGDI = ObjToGDI(TextObj->Font, FONT);
+  TEXTOBJ_UnlockText(TextObj);
+
+  Count = ftGdiGetKerningPairs(FontGDI,0,NULL);
+
+  if ( Count && krnpair )
+  {
+     if (Count > NumPairs)
+     {
+        SetLastWin32Error(ERROR_INSUFFICIENT_BUFFER);
+        return 0;
+     }
+     pKP = ExAllocatePoolWithTag(PagedPool, Count * sizeof(KERNINGPAIR), TAG_GDITEXT);
+     if (!pKP)
+     {
+        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        return 0;
+     }
+     ftGdiGetKerningPairs(FontGDI,Count,pKP);
+     _SEH2_TRY
+     {
+        ProbeForWrite(krnpair, Count * sizeof(KERNINGPAIR), 1);
+        RtlCopyMemory(krnpair, pKP, Count * sizeof(KERNINGPAIR));
+     }
+     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+     {
+        Status = _SEH2_GetExceptionCode();
+     }
+     _SEH2_END
+     if (!NT_SUCCESS(Status))
+     {
+        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        Count = 0;
+     }     
+     ExFreePoolWithTag(pKP,TAG_GDITEXT);
+  }
+  return Count;
 }
 
 /*
@@ -109,7 +472,7 @@ NtGdiGetKerningPairs(HDC  hDC,
  472, this is NtGdiGetOutlineTextMetricsInternalW.
  */
 ULONG
-STDCALL
+APIENTRY
 NtGdiGetOutlineTextMetricsInternalW (HDC  hDC,
                                    ULONG  Data,
                       OUTLINETEXTMETRICW  *otm,
@@ -122,56 +485,237 @@ NtGdiGetOutlineTextMetricsInternalW (HDC  hDC,
   HFONT hFont = 0;
   ULONG Size;
   OUTLINETEXTMETRICW *potm;
-  NTSTATUS Status;
+  NTSTATUS Status = STATUS_SUCCESS;
 
   dc = DC_LockDc(hDC);
-  if (dc == NULL)
-    {
-      SetLastWin32Error(ERROR_INVALID_HANDLE);
-      return 0;
-    }
+  if (!dc)
+  {
+     SetLastWin32Error(ERROR_INVALID_HANDLE);
+     return 0;
+  }
   Dc_Attr = dc->pDc_Attr;
   if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
   hFont = Dc_Attr->hlfntNew;
-  TextObj = TEXTOBJ_LockText(hFont);
+  TextObj = RealizeFontInit(hFont);
   DC_UnlockDc(dc);
-  if (TextObj == NULL)
-    {
-      SetLastWin32Error(ERROR_INVALID_HANDLE);
-      return 0;
-    }
+  if (!TextObj)
+  {
+     SetLastWin32Error(ERROR_INVALID_HANDLE);
+     return 0;
+  }
   FontGDI = ObjToGDI(TextObj->Font, FONT);
   TEXTOBJ_UnlockText(TextObj);
   Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
   if (!otm) return Size;
   if (Size > Data)
-    {
+  {
       SetLastWin32Error(ERROR_INSUFFICIENT_BUFFER);
       return 0;
-    }
+  }
   potm = ExAllocatePoolWithTag(PagedPool, Size, TAG_GDITEXT);
-  if (NULL == potm)
-    {
+  if (!potm)
+  {
       SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
       return 0;
-    }
+  }
   IntGetOutlineTextMetrics(FontGDI, Size, potm);
   if (otm)
+  {
+     _SEH2_TRY
+     {
+         ProbeForWrite(otm, Size, 1);
+         RtlCopyMemory(otm, potm, Size);
+     }
+     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+     {
+         Status = _SEH2_GetExceptionCode();
+     }
+     _SEH2_END
+
+     if (!NT_SUCCESS(Status))
+     {
+        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        Size = 0;
+     }
+  }
+  ExFreePoolWithTag(potm,TAG_GDITEXT);
+  return Size;
+}
+
+W32KAPI
+BOOL
+APIENTRY
+NtGdiGetFontResourceInfoInternalW(
+    IN LPWSTR   pwszFiles,
+    IN ULONG    cwc,
+    IN ULONG    cFiles,
+    IN UINT     cjIn,
+    OUT LPDWORD pdwBytes,
+    OUT LPVOID  pvBuf,
+    IN DWORD    dwType)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    DWORD dwBytes;
+    UNICODE_STRING SafeFileNames;
+    BOOL bRet = FALSE;
+    ULONG cbStringSize;
+
+    union
+    {
+        LOGFONTW logfontw;
+        WCHAR FullName[LF_FULLFACESIZE];
+    } Buffer;
+
+    /* FIXME: handle cFiles > 0 */
+
+    /* Check for valid dwType values
+       dwType == 4 seems to be handled by gdi32 only */
+    if (dwType == 4 || dwType > 5)
+    {
+        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    /* Allocate a safe unicode string buffer */
+    cbStringSize = cwc * sizeof(WCHAR);
+    SafeFileNames.MaximumLength = SafeFileNames.Length = cbStringSize - sizeof(WCHAR);
+    SafeFileNames.Buffer = ExAllocatePoolWithTag(PagedPool,
+                                                 cbStringSize,
+                                                 TAG('R','T','S','U'));
+    if (!SafeFileNames.Buffer)
+    {
+        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
+    }
+
+    /* Check buffers and copy pwszFiles to safe unicode string */
+    _SEH2_TRY
+    {
+        ProbeForRead(pwszFiles, cbStringSize, 1);
+        ProbeForWrite(pdwBytes, sizeof(DWORD), 1);
+        ProbeForWrite(pvBuf, cjIn, 1);
+
+        RtlCopyMemory(SafeFileNames.Buffer, pwszFiles, cbStringSize);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = _SEH2_GetExceptionCode();
+    }
+    _SEH2_END
+
+    if(!NT_SUCCESS(Status))
+    {
+        SetLastNtError(Status);
+        /* Free the string buffer for the safe filename */
+        ExFreePoolWithTag(SafeFileNames.Buffer,TAG('R','T','S','U'));
+        return FALSE;
+    }
+
+    /* Do the actual call */
+    bRet = IntGdiGetFontResourceInfo(&SafeFileNames, &Buffer, &dwBytes, dwType);
+
+    /* Check if succeeded and the buffer is big enough */
+    if (bRet && cjIn >= dwBytes)
     {
-      Status = MmCopyToCaller(otm, potm, Size);
-      if (! NT_SUCCESS(Status))
+        /* Copy the data back to caller */
+        _SEH2_TRY
+        {
+            /* Buffers are already probed */
+            RtlCopyMemory(pvBuf, &Buffer, dwBytes);
+            *pdwBytes = dwBytes;
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            Status = _SEH2_GetExceptionCode();
+        }
+        _SEH2_END
+
+        if(!NT_SUCCESS(Status))
         {
-          SetLastWin32Error(ERROR_INVALID_PARAMETER);
-          ExFreePool(potm);
-          return 0;
+            SetLastNtError(Status);
+            bRet = FALSE;
         }
     }
-  ExFreePool(potm);
-  return Size;
+
+    /* Free the string for the safe filenames */
+    ExFreePoolWithTag(SafeFileNames.Buffer,TAG('R','T','S','U'));
+
+    return bRet;
+}
+
+ /*
+ * @unimplemented
+ */
+BOOL
+APIENTRY
+NtGdiGetRealizationInfo(
+    IN HDC hdc,
+    OUT PREALIZATION_INFO pri,
+    IN HFONT hf)
+{
+  PDC pDc;
+  PTEXTOBJ pTextObj;
+  PFONTGDI pFontGdi;
+  PDC_ATTR Dc_Attr;
+  BOOL Ret = FALSE;
+  INT i = 0;
+  REALIZATION_INFO ri;
+
+  pDc = DC_LockDc(hdc);
+  if (!pDc)
+  {
+     SetLastWin32Error(ERROR_INVALID_HANDLE);
+     return 0;
+  }
+  Dc_Attr = pDc->pDc_Attr;
+  if(!Dc_Attr) Dc_Attr = &pDc->Dc_Attr;
+  pTextObj = RealizeFontInit(Dc_Attr->hlfntNew);
+  pFontGdi = ObjToGDI(pTextObj->Font, FONT);
+  TEXTOBJ_UnlockText(pTextObj);
+  DC_UnlockDc(pDc);
+
+  Ret = ftGdiRealizationInfo(pFontGdi, &ri);
+  if (Ret)
+  {
+     if (pri)
+     {
+        NTSTATUS Status = STATUS_SUCCESS;
+        _SEH2_TRY
+        {
+            ProbeForWrite(pri, sizeof(REALIZATION_INFO), 1);
+            RtlCopyMemory(pri, &ri, sizeof(REALIZATION_INFO));
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            Status = _SEH2_GetExceptionCode();
+        }
+        _SEH2_END
+
+        if(!NT_SUCCESS(Status))
+        {
+            SetLastNtError(Status);
+            return FALSE;
+        }
+     }
+     do
+     {
+        if (GdiHandleTable->cfPublic[i].hf == hf)
+        {
+           GdiHandleTable->cfPublic[i].iTechnology = ri.iTechnology;
+           GdiHandleTable->cfPublic[i].iUniq = ri.iUniq;
+           GdiHandleTable->cfPublic[i].dwUnknown = ri.dwUnknown;
+           GdiHandleTable->cfPublic[i].dwCFCount = GdiHandleTable->dwCFCount;
+           GdiHandleTable->cfPublic[i].fl |= CFONT_REALIZATION;
+        }
+        i++;
+     }
+     while ( i < GDI_CFONT_MAX );
+  }
+  return Ret;
 }
 
 HFONT
-STDCALL
+APIENTRY
 NtGdiHfontCreate(
   IN PENUMLOGFONTEXDVW pelfw,
   IN ULONG cjElfw,
@@ -184,21 +728,25 @@ NtGdiHfontCreate(
   PTEXTOBJ TextObj;
   NTSTATUS Status = STATUS_SUCCESS;
 
+  /* Silence GCC warnings */
+  SafeLogfont.elfEnumLogfontEx.elfLogFont.lfEscapement = 0;
+  SafeLogfont.elfEnumLogfontEx.elfLogFont.lfOrientation = 0;
+
   if (!pelfw)
   {
       return NULL;
   }
 
-  _SEH_TRY
+  _SEH2_TRY
   {
       ProbeForRead(pelfw, sizeof(ENUMLOGFONTEXDVW), 1);
       RtlCopyMemory(&SafeLogfont, pelfw, sizeof(ENUMLOGFONTEXDVW));
   }
-  _SEH_HANDLE
+  _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
   {
-      Status = _SEH_GetExceptionCode();
+      Status = _SEH2_GetExceptionCode();
   }
-  _SEH_END
+  _SEH2_END
 
   if (!NT_SUCCESS(Status))
   {
@@ -212,6 +760,8 @@ NtGdiHfontCreate(
   }
   hNewFont = TextObj->BaseObject.hHmgr;
 
+  TextObj->lft = lft;
+  TextObj->fl  = fl;
   RtlCopyMemory (&TextObj->logfont, &SafeLogfont, sizeof(ENUMLOGFONTEXDVW));
 
   if (SafeLogfont.elfEnumLogfontEx.elfLogFont.lfEscapement !=
@@ -226,5 +776,41 @@ NtGdiHfontCreate(
   return hNewFont;
 }
 
+/*
+ * @implemented
+ */
+HFONT
+APIENTRY
+NtGdiSelectFont(
+    IN HDC hDC,
+    IN HFONT hFont)
+{
+    PDC pDC;
+    PDC_ATTR pDc_Attr;
+    HFONT hOrgFont = NULL;
+
+    if (hDC == NULL || hFont == NULL) return NULL;
+
+    pDC = DC_LockDc(hDC);
+    if (!pDC)
+    {
+        return NULL;
+    }
+
+    pDc_Attr = pDC->pDc_Attr;
+    if(!pDc_Attr) pDc_Attr = &pDC->Dc_Attr;
+
+    /* FIXME: what if not successful? */
+    if(NT_SUCCESS(TextIntRealizeFont((HFONT)hFont,NULL)))
+    {
+        hOrgFont = pDc_Attr->hlfntNew;
+        pDc_Attr->hlfntNew = hFont;
+    }
+
+    DC_UnlockDc(pDC);
+
+    return hOrgFont;
+}
+
 
 /* EOF */