tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ftsystem.c (13398B)


      1 /****************************************************************************
      2 *
      3 * ftsystem.c
      4 *
      5 *   Windows-specific FreeType low-level system interface (body).
      6 *
      7 * Copyright (C) 2021-2025 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  /* support for Universal Windows Platform UWP, formerly WinRT */
    200 #ifdef _WINRT_DLL
    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  /* _WINRT_DLL */
    252 
    253 
    254  /* support for Windows CE */
    255 #ifdef _WIN32_WCE
    256 
    257  /* malloc.h provides implementation of alloca()/_alloca() */
    258  #include <malloc.h>
    259 
    260  FT_LOCAL_DEF( HANDLE )
    261  CreateFileA( LPCSTR                 lpFileName,
    262               DWORD                  dwDesiredAccess,
    263               DWORD                  dwShareMode,
    264               LPSECURITY_ATTRIBUTES  lpSecurityAttributes,
    265               DWORD                  dwCreationDisposition,
    266               DWORD                  dwFlagsAndAttributes,
    267               HANDLE                 hTemplateFile )
    268  {
    269    int     len;
    270    LPWSTR  lpFileNameW;
    271 
    272 
    273    /* allocate memory space for converted path name */
    274    len = MultiByteToWideChar( CP_ACP, MB_ERR_INVALID_CHARS,
    275                               lpFileName, -1, NULL, 0 );
    276 
    277    lpFileNameW = (LPWSTR)_alloca( len * sizeof ( WCHAR ) );
    278 
    279    if ( !len || !lpFileNameW )
    280    {
    281      FT_ERROR(( "FT_Stream_Open: cannot convert file name to LPWSTR\n" ));
    282      return INVALID_HANDLE_VALUE;
    283    }
    284 
    285    /* now it is safe to do the translation */
    286    MultiByteToWideChar( CP_ACP, MB_ERR_INVALID_CHARS,
    287                         lpFileName, -1, lpFileNameW, len );
    288 
    289    /* open the file */
    290    return CreateFileW( lpFileNameW, dwDesiredAccess, dwShareMode,
    291                        lpSecurityAttributes, dwCreationDisposition,
    292                        dwFlagsAndAttributes, hTemplateFile );
    293  }
    294 
    295 #endif  /* _WIN32_WCE */
    296 
    297  /* support for really old Windows */
    298 #if defined( _WIN32_WCE ) || defined ( _WIN32_WINDOWS ) || \
    299    ( defined( _WIN32_WINNT ) && _WIN32_WINNT <= 0x0400 )
    300 
    301  FT_LOCAL_DEF( BOOL )
    302  GetFileSizeEx( HANDLE          hFile,
    303                 PLARGE_INTEGER  lpFileSize )
    304  {
    305    lpFileSize->u.LowPart = GetFileSize( hFile,
    306                                         (DWORD *)&lpFileSize->u.HighPart );
    307 
    308    if ( lpFileSize->u.LowPart == INVALID_FILE_SIZE &&
    309         GetLastError() != NO_ERROR                 )
    310      return FALSE;
    311    else
    312      return TRUE;
    313  }
    314 
    315 #endif  /* _WIN32_WCE || _WIN32_WINDOWS || _WIN32_WINNT <= 0x0400 */
    316 
    317 
    318  /* documentation is in ftobjs.h */
    319 
    320  FT_BASE_DEF( FT_Error )
    321  FT_Stream_Open( FT_Stream    stream,
    322                  const char*  filepathname )
    323  {
    324    HANDLE         file;
    325    HANDLE         fm;
    326    LARGE_INTEGER  size;
    327 
    328 
    329    if ( !stream )
    330      return FT_THROW( Invalid_Stream_Handle );
    331 
    332    /* open the file */
    333    file = CreateFileA( (LPCSTR)filepathname, GENERIC_READ, FILE_SHARE_READ,
    334                        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
    335    if ( file == INVALID_HANDLE_VALUE )
    336    {
    337      FT_ERROR(( "FT_Stream_Open:" ));
    338      FT_ERROR(( " could not open `%s'\n", filepathname ));
    339      return FT_THROW( Cannot_Open_Resource );
    340    }
    341 
    342    if ( GetFileSizeEx( file, &size ) == FALSE )
    343    {
    344      FT_ERROR(( "FT_Stream_Open:" ));
    345      FT_ERROR(( " could not retrieve size of file `%s'\n", filepathname ));
    346      goto Fail_Open;
    347    }
    348 
    349    /* `stream->size' is typedef'd to unsigned long (in `ftsystem.h'); */
    350    /* So avoid overflow caused by fonts in huge files larger than     */
    351    /* 2GB, do a test.                                                 */
    352    if ( size.QuadPart > LONG_MAX )
    353    {
    354      FT_ERROR(( "FT_Stream_Open: file is too big\n" ));
    355      goto Fail_Open;
    356    }
    357    else if ( size.QuadPart == 0 )
    358    {
    359      FT_ERROR(( "FT_Stream_Open: zero-length file\n" ));
    360      goto Fail_Open;
    361    }
    362 
    363    fm = CreateFileMapping( file, NULL, PAGE_READONLY, 0, 0, NULL );
    364    if ( fm == NULL )
    365    {
    366      FT_ERROR(( "FT_Stream_Open: can not map file\n" ));
    367      goto Fail_Open;
    368    }
    369 
    370    /* Store only the low part of this 64 bits integer because long is */
    371    /* a 32 bits type. Anyway, a check has been done above to forbid   */
    372    /* a size greater than LONG_MAX                                    */
    373    stream->size = size.LowPart;
    374    stream->pos  = 0;
    375    stream->base = (unsigned char *)
    376                     MapViewOfFile( fm, FILE_MAP_READ, 0, 0, 0 );
    377 
    378    CloseHandle( fm );
    379 
    380    if ( stream->base != NULL )
    381      stream->close = ft_close_stream_by_munmap;
    382    else
    383    {
    384      DWORD  total_read_count;
    385 
    386 
    387      FT_ERROR(( "FT_Stream_Open:" ));
    388      FT_ERROR(( " could not `mmap' file `%s'\n", filepathname ));
    389 
    390      stream->base = (unsigned char*)ft_alloc( stream->memory, stream->size );
    391 
    392      if ( !stream->base )
    393      {
    394        FT_ERROR(( "FT_Stream_Open:" ));
    395        FT_ERROR(( " could not `alloc' memory\n" ));
    396        goto Fail_Open;
    397      }
    398 
    399      total_read_count = 0;
    400      do
    401      {
    402        DWORD  read_count;
    403 
    404 
    405        if ( ReadFile( file,
    406                       stream->base + total_read_count,
    407                       stream->size - total_read_count,
    408                       &read_count, NULL ) == FALSE )
    409        {
    410          FT_ERROR(( "FT_Stream_Open:" ));
    411          FT_ERROR(( " error while `read'ing file `%s'\n", filepathname ));
    412          goto Fail_Read;
    413        }
    414 
    415        total_read_count += read_count;
    416 
    417      } while ( total_read_count != stream->size );
    418 
    419      stream->close = ft_close_stream_by_free;
    420    }
    421 
    422    CloseHandle( file );
    423 
    424    stream->descriptor.pointer = stream->base;
    425    stream->pathname.pointer   = (char*)filepathname;
    426 
    427    stream->read = NULL;
    428 
    429    FT_TRACE1(( "FT_Stream_Open:" ));
    430    FT_TRACE1(( " opened `%s' (%ld bytes) successfully\n",
    431                filepathname, stream->size ));
    432 
    433    return FT_Err_Ok;
    434 
    435  Fail_Read:
    436    ft_free( stream->memory, stream->base );
    437 
    438  Fail_Open:
    439    CloseHandle( file );
    440 
    441    stream->base = NULL;
    442    stream->size = 0;
    443    stream->pos  = 0;
    444 
    445    return FT_THROW( Cannot_Open_Stream );
    446  }
    447 
    448 
    449 #ifdef FT_DEBUG_MEMORY
    450 
    451  extern FT_Int
    452  ft_mem_debug_init( FT_Memory  memory );
    453 
    454  extern void
    455  ft_mem_debug_done( FT_Memory  memory );
    456 
    457 #endif
    458 
    459 
    460  /* documentation is in ftobjs.h */
    461 
    462  FT_BASE_DEF( FT_Memory )
    463  FT_New_Memory( void )
    464  {
    465    HANDLE     heap;
    466    FT_Memory  memory;
    467 
    468 
    469    heap   = GetProcessHeap();
    470    memory = heap ? (FT_Memory)HeapAlloc( heap, 0, sizeof ( *memory ) )
    471                  : NULL;
    472 
    473    if ( memory )
    474    {
    475      memory->user    = heap;
    476      memory->alloc   = ft_alloc;
    477      memory->realloc = ft_realloc;
    478      memory->free    = ft_free;
    479 #ifdef FT_DEBUG_MEMORY
    480      ft_mem_debug_init( memory );
    481 #endif
    482    }
    483 
    484    return memory;
    485  }
    486 
    487 
    488  /* documentation is in ftobjs.h */
    489 
    490  FT_BASE_DEF( void )
    491  FT_Done_Memory( FT_Memory  memory )
    492  {
    493 #ifdef FT_DEBUG_MEMORY
    494    ft_mem_debug_done( memory );
    495 #endif
    496    memory->free( memory, memory );
    497  }
    498 
    499 
    500 /* END */