(root)/
freetype-2.13.2/
builds/
windows/
ftsystem.c
       1  /****************************************************************************
       2   *
       3   * ftsystem.c
       4   *
       5   *   Windows-specific FreeType low-level system interface (body).
       6   *
       7   * Copyright (C) 2021-2023 by
       8   * David Turner, Robert Wilhelm, and Werner Lemberg.
       9   *
      10   * This file is part of the FreeType project, and may only be used,
      11   * modified, and distributed under the terms of the FreeType project
      12   * license, LICENSE.TXT.  By continuing to use, modify, or distribute
      13   * this file you indicate that you have read the license and
      14   * understand and accept it fully.
      15   *
      16   */
      17  
      18  
      19  #include <ft2build.h>
      20    /* we use our special ftconfig.h file, not the standard one */
      21  #include FT_CONFIG_CONFIG_H
      22  #include <freetype/internal/ftdebug.h>
      23  #include <freetype/ftsystem.h>
      24  #include <freetype/fterrors.h>
      25  #include <freetype/fttypes.h>
      26  #include <freetype/internal/ftstream.h>
      27  
      28    /* memory mapping and allocation includes and definitions */
      29  #define WIN32_LEAN_AND_MEAN
      30  #include <windows.h>
      31  
      32  
      33    /**************************************************************************
      34     *
      35     *                      MEMORY MANAGEMENT INTERFACE
      36     *
      37     */
      38  
      39  
      40    /**************************************************************************
      41     *
      42     * It is not necessary to do any error checking for the
      43     * allocation-related functions.  This will be done by the higher level
      44     * routines like ft_mem_alloc() or ft_mem_realloc().
      45     *
      46     */
      47  
      48  
      49    /**************************************************************************
      50     *
      51     * @Function:
      52     *   ft_alloc
      53     *
      54     * @Description:
      55     *   The memory allocation function.
      56     *
      57     * @Input:
      58     *   memory ::
      59     *     A pointer to the memory object.
      60     *
      61     *   size ::
      62     *     The requested size in bytes.
      63     *
      64     * @Return:
      65     *   The address of newly allocated block.
      66     */
      67    FT_CALLBACK_DEF( void* )
      68    ft_alloc( FT_Memory  memory,
      69              long       size )
      70    {
      71      return HeapAlloc( memory->user, 0, size );
      72    }
      73  
      74  
      75    /**************************************************************************
      76     *
      77     * @Function:
      78     *   ft_realloc
      79     *
      80     * @Description:
      81     *   The memory reallocation function.
      82     *
      83     * @Input:
      84     *   memory ::
      85     *     A pointer to the memory object.
      86     *
      87     *   cur_size ::
      88     *     The current size of the allocated memory block.
      89     *
      90     *   new_size ::
      91     *     The newly requested size in bytes.
      92     *
      93     *   block ::
      94     *     The current address of the block in memory.
      95     *
      96     * @Return:
      97     *   The address of the reallocated memory block.
      98     */
      99    FT_CALLBACK_DEF( void* )
     100    ft_realloc( FT_Memory  memory,
     101                long       cur_size,
     102                long       new_size,
     103                void*      block )
     104    {
     105      FT_UNUSED( cur_size );
     106  
     107      return HeapReAlloc( memory->user, 0, block, new_size );
     108    }
     109  
     110  
     111    /**************************************************************************
     112     *
     113     * @Function:
     114     *   ft_free
     115     *
     116     * @Description:
     117     *   The memory release function.
     118     *
     119     * @Input:
     120     *   memory ::
     121     *     A pointer to the memory object.
     122     *
     123     *   block ::
     124     *     The address of block in memory to be freed.
     125     */
     126    FT_CALLBACK_DEF( void )
     127    ft_free( FT_Memory  memory,
     128             void*      block )
     129    {
     130      HeapFree( memory->user, 0, block );
     131    }
     132  
     133  
     134    /**************************************************************************
     135     *
     136     *                    RESOURCE MANAGEMENT INTERFACE
     137     *
     138     */
     139  
     140  
     141    /**************************************************************************
     142     *
     143     * The macro FT_COMPONENT is used in trace mode.  It is an implicit
     144     * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
     145     * messages during execution.
     146     */
     147  #undef  FT_COMPONENT
     148  #define FT_COMPONENT  io
     149  
     150    /* We use the macro STREAM_FILE for convenience to extract the       */
     151    /* system-specific stream handle from a given FreeType stream object */
     152  #define STREAM_FILE( stream )  ( (FILE*)stream->descriptor.pointer )
     153  
     154  
     155    /**************************************************************************
     156     *
     157     * @Function:
     158     *   ft_close_stream_by_munmap
     159     *
     160     * @Description:
     161     *   The function to close a stream which is opened by mmap.
     162     *
     163     * @Input:
     164     *   stream :: A pointer to the stream object.
     165     */
     166    FT_CALLBACK_DEF( void )
     167    ft_close_stream_by_munmap( FT_Stream  stream )
     168    {
     169      UnmapViewOfFile( (LPCVOID)stream->descriptor.pointer );
     170  
     171      stream->descriptor.pointer = NULL;
     172      stream->size               = 0;
     173      stream->base               = NULL;
     174    }
     175  
     176  
     177    /**************************************************************************
     178     *
     179     * @Function:
     180     *   ft_close_stream_by_free
     181     *
     182     * @Description:
     183     *   The function to close a stream which is created by ft_alloc.
     184     *
     185     * @Input:
     186     *   stream :: A pointer to the stream object.
     187     */
     188    FT_CALLBACK_DEF( void )
     189    ft_close_stream_by_free( FT_Stream  stream )
     190    {
     191      ft_free( stream->memory, stream->descriptor.pointer );
     192  
     193      stream->descriptor.pointer = NULL;
     194      stream->size               = 0;
     195      stream->base               = NULL;
     196    }
     197  
     198  
     199    /* non-desktop Universal Windows Platform */
     200  #if defined( WINAPI_FAMILY ) && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP
     201  
     202  #define PACK_DWORD64( hi, lo )  ( ( (DWORD64)(hi) << 32 ) | (DWORD)(lo) )
     203  
     204  #define CreateFileMapping( a, b, c, d, e, f )                          \
     205            CreateFileMappingFromApp( a, b, c, PACK_DWORD64( d, e ), f )
     206  #define MapViewOfFile( a, b, c, d, e )                                 \
     207            MapViewOfFileFromApp( a, b, PACK_DWORD64( c, d ), e )
     208  
     209    FT_LOCAL_DEF( HANDLE )
     210    CreateFileA( LPCSTR                 lpFileName,
     211                 DWORD                  dwDesiredAccess,
     212                 DWORD                  dwShareMode,
     213                 LPSECURITY_ATTRIBUTES  lpSecurityAttributes,
     214                 DWORD                  dwCreationDisposition,
     215                 DWORD                  dwFlagsAndAttributes,
     216                 HANDLE                 hTemplateFile )
     217    {
     218      int     len;
     219      LPWSTR  lpFileNameW;
     220  
     221      CREATEFILE2_EXTENDED_PARAMETERS  createExParams = {
     222        sizeof ( CREATEFILE2_EXTENDED_PARAMETERS ),
     223        dwFlagsAndAttributes & 0x0000FFFF,
     224        dwFlagsAndAttributes & 0xFFF00000,
     225        dwFlagsAndAttributes & 0x000F0000,
     226        lpSecurityAttributes,
     227        hTemplateFile };
     228  
     229  
     230      /* allocate memory space for converted path name */
     231      len = MultiByteToWideChar( CP_ACP, MB_ERR_INVALID_CHARS,
     232                                 lpFileName, -1, NULL, 0 );
     233  
     234      lpFileNameW = (LPWSTR)_alloca( len * sizeof ( WCHAR ) );
     235  
     236      if ( !len || !lpFileNameW )
     237      {
     238        FT_ERROR(( "FT_Stream_Open: cannot convert file name to LPWSTR\n" ));
     239        return INVALID_HANDLE_VALUE;
     240      }
     241  
     242      /* now it is safe to do the translation */
     243      MultiByteToWideChar( CP_ACP, MB_ERR_INVALID_CHARS,
     244                           lpFileName, -1, lpFileNameW, len );
     245  
     246      /* open the file */
     247      return CreateFile2( lpFileNameW, dwDesiredAccess, dwShareMode,
     248                          dwCreationDisposition, &createExParams );
     249    }
     250  
     251  #endif
     252  
     253  
     254  #if defined( _WIN32_WCE )
     255  
     256    /* malloc.h provides implementation of alloca()/_alloca() */
     257    #include <malloc.h>
     258  
     259    FT_LOCAL_DEF( HANDLE )
     260    CreateFileA( LPCSTR                 lpFileName,
     261                 DWORD                  dwDesiredAccess,
     262                 DWORD                  dwShareMode,
     263                 LPSECURITY_ATTRIBUTES  lpSecurityAttributes,
     264                 DWORD                  dwCreationDisposition,
     265                 DWORD                  dwFlagsAndAttributes,
     266                 HANDLE                 hTemplateFile )
     267    {
     268      int     len;
     269      LPWSTR  lpFileNameW;
     270  
     271  
     272      /* allocate memory space for converted path name */
     273      len = MultiByteToWideChar( CP_ACP, MB_ERR_INVALID_CHARS,
     274                                 lpFileName, -1, NULL, 0 );
     275  
     276      lpFileNameW = (LPWSTR)_alloca( len * sizeof ( WCHAR ) );
     277  
     278      if ( !len || !lpFileNameW )
     279      {
     280        FT_ERROR(( "FT_Stream_Open: cannot convert file name to LPWSTR\n" ));
     281        return INVALID_HANDLE_VALUE;
     282      }
     283  
     284      /* now it is safe to do the translation */
     285      MultiByteToWideChar( CP_ACP, MB_ERR_INVALID_CHARS,
     286                           lpFileName, -1, lpFileNameW, len );
     287  
     288      /* open the file */
     289      return CreateFileW( lpFileNameW, dwDesiredAccess, dwShareMode,
     290                          lpSecurityAttributes, dwCreationDisposition,
     291                          dwFlagsAndAttributes, hTemplateFile );
     292    }
     293  
     294  #endif
     295  
     296  
     297  #if defined( _WIN32_WCE ) || defined ( _WIN32_WINDOWS ) || \
     298      !defined( _WIN32_WINNT ) || _WIN32_WINNT <= 0x0400
     299  
     300    FT_LOCAL_DEF( BOOL )
     301    GetFileSizeEx( HANDLE          hFile,
     302                   PLARGE_INTEGER  lpFileSize )
     303    {
     304      lpFileSize->u.LowPart = GetFileSize( hFile,
     305                                           (DWORD *)&lpFileSize->u.HighPart );
     306  
     307      if ( lpFileSize->u.LowPart == INVALID_FILE_SIZE &&
     308           GetLastError() != NO_ERROR                 )
     309        return FALSE;
     310      else
     311        return TRUE;
     312    }
     313  
     314  #endif
     315  
     316  
     317    /* documentation is in ftobjs.h */
     318  
     319    FT_BASE_DEF( FT_Error )
     320    FT_Stream_Open( FT_Stream    stream,
     321                    const char*  filepathname )
     322    {
     323      HANDLE         file;
     324      HANDLE         fm;
     325      LARGE_INTEGER  size;
     326  
     327  
     328      if ( !stream )
     329        return FT_THROW( Invalid_Stream_Handle );
     330  
     331      /* open the file */
     332      file = CreateFileA( (LPCSTR)filepathname, GENERIC_READ, FILE_SHARE_READ,
     333                          NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
     334      if ( file == INVALID_HANDLE_VALUE )
     335      {
     336        FT_ERROR(( "FT_Stream_Open:" ));
     337        FT_ERROR(( " could not open `%s'\n", filepathname ));
     338        return FT_THROW( Cannot_Open_Resource );
     339      }
     340  
     341      if ( GetFileSizeEx( file, &size ) == FALSE )
     342      {
     343        FT_ERROR(( "FT_Stream_Open:" ));
     344        FT_ERROR(( " could not retrieve size of file `%s'\n", filepathname ));
     345        goto Fail_Open;
     346      }
     347  
     348      /* `stream->size' is typedef'd to unsigned long (in `ftsystem.h'); */
     349      /* So avoid overflow caused by fonts in huge files larger than     */
     350      /* 2GB, do a test.                                                 */
     351      if ( size.QuadPart > LONG_MAX )
     352      {
     353        FT_ERROR(( "FT_Stream_Open: file is too big\n" ));
     354        goto Fail_Open;
     355      }
     356      else if ( size.QuadPart == 0 )
     357      {
     358        FT_ERROR(( "FT_Stream_Open: zero-length file\n" ));
     359        goto Fail_Open;
     360      }
     361  
     362      fm = CreateFileMapping( file, NULL, PAGE_READONLY, 0, 0, NULL );
     363      if ( fm == NULL )
     364      {
     365        FT_ERROR(( "FT_Stream_Open: can not map file\n" ));
     366        goto Fail_Open;
     367      }
     368  
     369      /* Store only the low part of this 64 bits integer because long is */
     370      /* a 32 bits type. Anyway, a check has been done above to forbid   */
     371      /* a size greater than LONG_MAX                                    */
     372      stream->size = size.LowPart;
     373      stream->pos  = 0;
     374      stream->base = (unsigned char *)
     375                       MapViewOfFile( fm, FILE_MAP_READ, 0, 0, 0 );
     376  
     377      CloseHandle( fm );
     378  
     379      if ( stream->base != NULL )
     380        stream->close = ft_close_stream_by_munmap;
     381      else
     382      {
     383        DWORD  total_read_count;
     384  
     385  
     386        FT_ERROR(( "FT_Stream_Open:" ));
     387        FT_ERROR(( " could not `mmap' file `%s'\n", filepathname ));
     388  
     389        stream->base = (unsigned char*)ft_alloc( stream->memory, stream->size );
     390  
     391        if ( !stream->base )
     392        {
     393          FT_ERROR(( "FT_Stream_Open:" ));
     394          FT_ERROR(( " could not `alloc' memory\n" ));
     395          goto Fail_Open;
     396        }
     397  
     398        total_read_count = 0;
     399        do
     400        {
     401          DWORD  read_count;
     402  
     403  
     404          if ( ReadFile( file,
     405                         stream->base + total_read_count,
     406                         stream->size - total_read_count,
     407                         &read_count, NULL ) == FALSE )
     408          {
     409            FT_ERROR(( "FT_Stream_Open:" ));
     410            FT_ERROR(( " error while `read'ing file `%s'\n", filepathname ));
     411            goto Fail_Read;
     412          }
     413  
     414          total_read_count += read_count;
     415  
     416        } while ( total_read_count != stream->size );
     417  
     418        stream->close = ft_close_stream_by_free;
     419      }
     420  
     421      CloseHandle( file );
     422  
     423      stream->descriptor.pointer = stream->base;
     424      stream->pathname.pointer   = (char*)filepathname;
     425  
     426      stream->read = NULL;
     427  
     428      FT_TRACE1(( "FT_Stream_Open:" ));
     429      FT_TRACE1(( " opened `%s' (%ld bytes) successfully\n",
     430                  filepathname, stream->size ));
     431  
     432      return FT_Err_Ok;
     433  
     434    Fail_Read:
     435      ft_free( stream->memory, stream->base );
     436  
     437    Fail_Open:
     438      CloseHandle( file );
     439  
     440      stream->base = NULL;
     441      stream->size = 0;
     442      stream->pos  = 0;
     443  
     444      return FT_THROW( Cannot_Open_Stream );
     445    }
     446  
     447  
     448  #ifdef FT_DEBUG_MEMORY
     449  
     450    extern FT_Int
     451    ft_mem_debug_init( FT_Memory  memory );
     452  
     453    extern void
     454    ft_mem_debug_done( FT_Memory  memory );
     455  
     456  #endif
     457  
     458  
     459    /* documentation is in ftobjs.h */
     460  
     461    FT_BASE_DEF( FT_Memory )
     462    FT_New_Memory( void )
     463    {
     464      HANDLE     heap;
     465      FT_Memory  memory;
     466  
     467  
     468      heap   = GetProcessHeap();
     469      memory = heap ? (FT_Memory)HeapAlloc( heap, 0, sizeof ( *memory ) )
     470                    : NULL;
     471  
     472      if ( memory )
     473      {
     474        memory->user    = heap;
     475        memory->alloc   = ft_alloc;
     476        memory->realloc = ft_realloc;
     477        memory->free    = ft_free;
     478  #ifdef FT_DEBUG_MEMORY
     479        ft_mem_debug_init( memory );
     480  #endif
     481      }
     482  
     483      return memory;
     484    }
     485  
     486  
     487    /* documentation is in ftobjs.h */
     488  
     489    FT_BASE_DEF( void )
     490    FT_Done_Memory( FT_Memory  memory )
     491    {
     492  #ifdef FT_DEBUG_MEMORY
     493      ft_mem_debug_done( memory );
     494  #endif
     495      memory->free( memory, memory );
     496    }
     497  
     498  
     499  /* END */