[WIN32SS] Rewrite font selection code. Patch by Katayama Hirofumi MZ. CORE-6621
[reactos.git] / reactos / win32ss / gdi / ntgdi / font.c
index 10bd73b..b3943f1 100644 (file)
@@ -1,9 +1,11 @@
 /*
  * PROJECT:         ReactOS win32 kernel mode subsystem
  * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            subsystems/win32/win32k/objects/font.c
+ * FILE:            win32ss/gdi/ntgdi/font.c
  * PURPOSE:         Font
- * PROGRAMMER:
+ * PROGRAMMERS:     James Tabor <james.tabor@reactos.org>
+ *                  Timo Kreuzer <timo.kreuzer@reactos.org>
+ *                  Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
  */
 
 /** Includes ******************************************************************/
 #define NDEBUG
 #include <debug.h>
 
+HFONT APIENTRY HfontCreate( IN PENUMLOGFONTEXDVW pelfw,IN ULONG cjElfw,IN LFTYPE lft,IN FLONG fl,IN PVOID pvCliData );
+
 /** Internal ******************************************************************/
 
+HFONT FASTCALL
+GreCreateFontIndirectW( LOGFONTW *lplf )
+{
+    if (lplf)
+    {
+        ENUMLOGFONTEXDVW Logfont;
+
+        RtlCopyMemory( &Logfont.elfEnumLogfontEx.elfLogFont, lplf, sizeof(LOGFONTW));
+        RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfFullName,
+                       sizeof(Logfont.elfEnumLogfontEx.elfFullName));
+        RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfStyle,
+                       sizeof(Logfont.elfEnumLogfontEx.elfStyle));
+        RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfScript,
+                       sizeof(Logfont.elfEnumLogfontEx.elfScript));
+
+        Logfont.elfDesignVector.dvNumAxes = 0;
+
+        RtlZeroMemory( &Logfont.elfDesignVector, sizeof(DESIGNVECTOR));
+
+        return HfontCreate((PENUMLOGFONTEXDVW)&Logfont, 0, 0, 0, NULL );
+    }
+    else return NULL;
+}
+
 DWORD
 FASTCALL
 GreGetKerningPairs(
@@ -91,7 +119,7 @@ DWORD
 FASTCALL
 GreGetCharacterPlacementW(
     HDC hdc,
-    LPWSTR pwsz,
+    LPCWSTR pwsz,
     INT nCount,
     INT nMaxExtent,
     LPGCP_RESULTSW pgcpw,
@@ -401,48 +429,53 @@ RealizeFontInit(HFONT hFont)
 INT
 APIENTRY
 NtGdiAddFontResourceW(
-    IN WCHAR *pwszFiles,
+    IN WCHAR *pwcFiles,
     IN ULONG cwc,
     IN ULONG cFiles,
     IN FLONG fl,
     IN DWORD dwPidTid,
     IN OPTIONAL DESIGNVECTOR *pdv)
 {
-  UNICODE_STRING SafeFileName;
-  PWSTR src;
-  NTSTATUS Status;
-  int Ret;
+    UNICODE_STRING SafeFileName;
+    INT Ret;
 
-  /* FIXME: Protect with SEH? */
-  RtlInitUnicodeString(&SafeFileName, pwszFiles);
+    DBG_UNREFERENCED_PARAMETER(cFiles);
+    DBG_UNREFERENCED_PARAMETER(dwPidTid);
+    DBG_UNREFERENCED_PARAMETER(pdv);
 
-  /* Reserve for prepending '\??\' */
-  SafeFileName.Length += 4 * sizeof(WCHAR);
-  SafeFileName.MaximumLength += 4 * sizeof(WCHAR);
+    DPRINT("NtGdiAddFontResourceW\n");
 
-  src = SafeFileName.Buffer;
-  SafeFileName.Buffer = (PWSTR)ExAllocatePoolWithTag(PagedPool, SafeFileName.MaximumLength, TAG_STRING);
-  if(!SafeFileName.Buffer)
-  {
-    EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
-    return 0;
-  }
+    /* cwc = Length + trailing zero. */
+    if (cwc <= 1 || cwc > UNICODE_STRING_MAX_CHARS)
+        return 0;
 
-  /* Prepend '\??\' */
-  RtlCopyMemory(SafeFileName.Buffer, L"\\??\\", 4 * sizeof(WCHAR));
+    SafeFileName.MaximumLength = cwc * sizeof(WCHAR);
+    SafeFileName.Length = SafeFileName.MaximumLength - sizeof(UNICODE_NULL);
+    SafeFileName.Buffer = ExAllocatePoolWithTag(PagedPool,
+                                                SafeFileName.MaximumLength,
+                                                TAG_STRING);
+    if (!SafeFileName.Buffer)
+    {
+        return 0;
+    }
 
-  Status = MmCopyFromCaller(SafeFileName.Buffer + 4, src, SafeFileName.MaximumLength - (4 * sizeof(WCHAR)));
-  if(!NT_SUCCESS(Status))
-  {
-    ExFreePoolWithTag(SafeFileName.Buffer, TAG_STRING);
-    SetLastNtError(Status);
-    return 0;
-  }
+    _SEH2_TRY
+    {
+        ProbeForRead(pwcFiles, cwc * sizeof(WCHAR), sizeof(WCHAR));
+        RtlCopyMemory(SafeFileName.Buffer, pwcFiles, SafeFileName.Length);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        ExFreePoolWithTag(SafeFileName.Buffer, TAG_STRING);
+        _SEH2_YIELD(return 0);
+    }
+    _SEH2_END;
 
-  Ret = IntGdiAddFontResource(&SafeFileName, (DWORD)fl);
+    SafeFileName.Buffer[SafeFileName.Length / sizeof(WCHAR)] = UNICODE_NULL;
+    Ret = IntGdiAddFontResource(&SafeFileName, fl);
 
-  ExFreePoolWithTag(SafeFileName.Buffer, TAG_STRING);
-  return Ret;
+    ExFreePoolWithTag(SafeFileName.Buffer, TAG_STRING);
+    return Ret;
 }
 
  /*
@@ -794,6 +827,7 @@ NtGdiGetOutlineTextMetricsInternalW (HDC  hDC,
      return 0;
   }
   FontGDI = ObjToGDI(TextObj->Font, FONT);
+  TextIntUpdateSize(dc, TextObj, FontGDI, TRUE);
   TEXTOBJ_UnlockText(TextObj);
   Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
   if (!otm) return Size;
@@ -836,31 +870,25 @@ 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)
+    IN LPWSTR       pwszFiles,
+    IN ULONG        cwc,
+    IN ULONG        cFiles,
+    IN UINT         cjIn,
+    IN OUT LPDWORD  pdwBytes,
+    OUT LPVOID      pvBuf,
+    IN DWORD        dwType)
 {
     NTSTATUS Status = STATUS_SUCCESS;
-    DWORD dwBytes;
+    DWORD dwBytes, dwBytesRequested;
     UNICODE_STRING SafeFileNames;
     BOOL bRet = FALSE;
     ULONG cbStringSize;
-
-    union
-    {
-        LOGFONTW logfontw;
-        WCHAR FullName[LF_FULLFACESIZE];
-    } Buffer;
+    LPVOID Buffer;
 
     /* FIXME: Handle cFiles > 0 */
 
-    /* Check for valid dwType values
-       dwType == 4 seems to be handled by gdi32 only */
-    if (dwType == 4 || dwType > 5)
+    /* Check for valid dwType values */
+    if (dwType > 5)
     {
         EngSetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
@@ -871,21 +899,34 @@ NtGdiGetFontResourceInfoInternalW(
     SafeFileNames.MaximumLength = SafeFileNames.Length = (USHORT)cbStringSize - sizeof(WCHAR);
     SafeFileNames.Buffer = ExAllocatePoolWithTag(PagedPool,
                                                  cbStringSize,
-                                                 'RTSU');
+                                                 TAG_USTR);
     if (!SafeFileNames.Buffer)
     {
         EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
         return FALSE;
     }
+    RtlZeroMemory(SafeFileNames.Buffer, SafeFileNames.MaximumLength);
 
     /* Check buffers and copy pwszFiles to safe unicode string */
     _SEH2_TRY
     {
         ProbeForRead(pwszFiles, cbStringSize, 1);
         ProbeForWrite(pdwBytes, sizeof(DWORD), 1);
-        ProbeForWrite(pvBuf, cjIn, 1);
+        if (pvBuf)
+            ProbeForWrite(pvBuf, cjIn, 1);
+
+        dwBytes = *pdwBytes;
+        dwBytesRequested = dwBytes;
 
         RtlCopyMemory(SafeFileNames.Buffer, pwszFiles, cbStringSize);
+        if (dwBytes > 0)
+        {
+            Buffer = ExAllocatePoolWithTag(PagedPool, dwBytes, TAG_FINF);
+        }
+        else
+        {
+            Buffer = ExAllocatePoolWithTag(PagedPool, sizeof(DWORD), TAG_FINF);
+        }
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
@@ -897,21 +938,24 @@ NtGdiGetFontResourceInfoInternalW(
     {
         SetLastNtError(Status);
         /* Free the string buffer for the safe filename */
-        ExFreePoolWithTag(SafeFileNames.Buffer,'RTSU');
+        ExFreePoolWithTag(SafeFileNames.Buffer, TAG_USTR);
         return FALSE;
     }
 
     /* Do the actual call */
-    bRet = IntGdiGetFontResourceInfo(&SafeFileNames, &Buffer, &dwBytes, dwType);
+    bRet = IntGdiGetFontResourceInfo(&SafeFileNames,
+                                     (pvBuf ? Buffer : NULL),
+                                     &dwBytes, dwType);
 
-    /* Check if succeeded and the buffer is big enough */
-    if (bRet && cjIn >= dwBytes)
+    /* Check if succeeded */
+    if (bRet)
     {
         /* Copy the data back to caller */
         _SEH2_TRY
         {
             /* Buffers are already probed */
-            RtlCopyMemory(pvBuf, &Buffer, dwBytes);
+            if (pvBuf && dwBytesRequested > 0)
+                RtlCopyMemory(pvBuf, Buffer, min(dwBytesRequested, dwBytes));
             *pdwBytes = dwBytes;
         }
         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
@@ -927,8 +971,9 @@ NtGdiGetFontResourceInfoInternalW(
         }
     }
 
+    ExFreePoolWithTag(Buffer, TAG_FINF);
     /* Free the string for the safe filenames */
-    ExFreePoolWithTag(SafeFileNames.Buffer,'RTSU');
+    ExFreePoolWithTag(SafeFileNames.Buffer, TAG_USTR);
 
     return bRet;
 }
@@ -1003,45 +1048,24 @@ NtGdiGetRealizationInfo(
   return Ret;
 }
 
+
 HFONT
 APIENTRY
-NtGdiHfontCreate(
+HfontCreate(
   IN PENUMLOGFONTEXDVW pelfw,
   IN ULONG cjElfw,
   IN LFTYPE lft,
   IN FLONG  fl,
   IN PVOID pvCliData )
 {
-  ENUMLOGFONTEXDVW SafeLogfont;
   HFONT hNewFont;
   PLFONT plfont;
-  NTSTATUS Status = STATUS_SUCCESS;
-
-  /* Silence GCC warnings */
-  SafeLogfont.elfEnumLogfontEx.elfLogFont.lfEscapement = 0;
-  SafeLogfont.elfEnumLogfontEx.elfLogFont.lfOrientation = 0;
 
   if (!pelfw)
   {
       return NULL;
   }
 
-  _SEH2_TRY
-  {
-      ProbeForRead(pelfw, sizeof(ENUMLOGFONTEXDVW), 1);
-      RtlCopyMemory(&SafeLogfont, pelfw, sizeof(ENUMLOGFONTEXDVW));
-  }
-  _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-  {
-      Status = _SEH2_GetExceptionCode();
-  }
-  _SEH2_END
-
-  if (!NT_SUCCESS(Status))
-  {
-      return NULL;
-  }
-
   plfont = LFONT_AllocFontWithHandle();
   if (!plfont)
   {
@@ -1051,11 +1075,11 @@ NtGdiHfontCreate(
 
   plfont->lft = lft;
   plfont->fl  = fl;
-  RtlCopyMemory (&plfont->logfont, &SafeLogfont, sizeof(ENUMLOGFONTEXDVW));
+  RtlCopyMemory (&plfont->logfont, pelfw, sizeof(ENUMLOGFONTEXDVW));
   ExInitializePushLock(&plfont->lock);
 
-  if (SafeLogfont.elfEnumLogfontEx.elfLogFont.lfEscapement !=
-      SafeLogfont.elfEnumLogfontEx.elfLogFont.lfOrientation)
+  if (pelfw->elfEnumLogfontEx.elfLogFont.lfEscapement !=
+      pelfw->elfEnumLogfontEx.elfLogFont.lfOrientation)
   {
     /* This should really depend on whether GM_ADVANCED is set */
     plfont->logfont.elfEnumLogfontEx.elfLogFont.lfOrientation =
@@ -1079,4 +1103,45 @@ NtGdiHfontCreate(
 }
 
 
+HFONT
+APIENTRY
+NtGdiHfontCreate(
+  IN PENUMLOGFONTEXDVW pelfw,
+  IN ULONG cjElfw,
+  IN LFTYPE lft,
+  IN FLONG  fl,
+  IN PVOID pvCliData )
+{
+  ENUMLOGFONTEXDVW SafeLogfont;
+  NTSTATUS Status = STATUS_SUCCESS;
+
+  /* Silence GCC warnings */
+  SafeLogfont.elfEnumLogfontEx.elfLogFont.lfEscapement = 0;
+  SafeLogfont.elfEnumLogfontEx.elfLogFont.lfOrientation = 0;
+
+  if (!pelfw)
+  {
+      return NULL;
+  }
+
+  _SEH2_TRY
+  {
+      ProbeForRead(pelfw, sizeof(ENUMLOGFONTEXDVW), 1);
+      RtlCopyMemory(&SafeLogfont, pelfw, sizeof(ENUMLOGFONTEXDVW));
+  }
+  _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+  {
+      Status = _SEH2_GetExceptionCode();
+  }
+  _SEH2_END
+
+  if (!NT_SUCCESS(Status))
+  {
+      return NULL;
+  }
+
+  return HfontCreate(&SafeLogfont, cjElfw, lft, fl, pvCliData);
+}
+
+
 /* EOF */