1 /****************************************************************************
5 * Windows-specific FreeType low-level system interface (body).
7 * Copyright (C) 2021-2023 by
8 * David Turner, Robert Wilhelm, and Werner Lemberg.
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.
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>
28 /* memory mapping and allocation includes and definitions */
29 #define WIN32_LEAN_AND_MEAN
33 /**************************************************************************
35 * MEMORY MANAGEMENT INTERFACE
40 /**************************************************************************
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().
49 /**************************************************************************
55 * The memory allocation function.
59 * A pointer to the memory object.
62 * The requested size in bytes.
65 * The address of newly allocated block.
67 FT_CALLBACK_DEF( void* )
68 ft_alloc( FT_Memory memory,
71 return HeapAlloc( memory->user, 0, size );
75 /**************************************************************************
81 * The memory reallocation function.
85 * A pointer to the memory object.
88 * The current size of the allocated memory block.
91 * The newly requested size in bytes.
94 * The current address of the block in memory.
97 * The address of the reallocated memory block.
99 FT_CALLBACK_DEF( void* )
100 ft_realloc( FT_Memory memory,
105 FT_UNUSED( cur_size );
107 return HeapReAlloc( memory->user, 0, block, new_size );
111 /**************************************************************************
117 * The memory release function.
121 * A pointer to the memory object.
124 * The address of block in memory to be freed.
126 FT_CALLBACK_DEF( void )
127 ft_free( FT_Memory memory,
130 HeapFree( memory->user, 0, block );
134 /**************************************************************************
136 * RESOURCE MANAGEMENT INTERFACE
141 /**************************************************************************
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.
148 #define FT_COMPONENT io
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 )
155 /**************************************************************************
158 * ft_close_stream_by_munmap
161 * The function to close a stream which is opened by mmap.
164 * stream :: A pointer to the stream object.
166 FT_CALLBACK_DEF( void )
167 ft_close_stream_by_munmap( FT_Stream stream )
169 UnmapViewOfFile( (LPCVOID)stream->descriptor.pointer );
171 stream->descriptor.pointer = NULL;
177 /**************************************************************************
180 * ft_close_stream_by_free
183 * The function to close a stream which is created by ft_alloc.
186 * stream :: A pointer to the stream object.
188 FT_CALLBACK_DEF( void )
189 ft_close_stream_by_free( FT_Stream stream )
191 ft_free( stream->memory, stream->descriptor.pointer );
193 stream->descriptor.pointer = NULL;
199 /* non-desktop Universal Windows Platform */
200 #if defined( WINAPI_FAMILY ) && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP
202 #define PACK_DWORD64( hi, lo ) ( ( (DWORD64)(hi) << 32 ) | (DWORD)(lo) )
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 )
209 FT_LOCAL_DEF( HANDLE )
210 CreateFileA( LPCSTR lpFileName,
211 DWORD dwDesiredAccess,
213 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
214 DWORD dwCreationDisposition,
215 DWORD dwFlagsAndAttributes,
216 HANDLE hTemplateFile )
221 CREATEFILE2_EXTENDED_PARAMETERS createExParams = {
222 sizeof ( CREATEFILE2_EXTENDED_PARAMETERS ),
223 dwFlagsAndAttributes & 0x0000FFFF,
224 dwFlagsAndAttributes & 0xFFF00000,
225 dwFlagsAndAttributes & 0x000F0000,
226 lpSecurityAttributes,
230 /* allocate memory space for converted path name */
231 len = MultiByteToWideChar( CP_ACP, MB_ERR_INVALID_CHARS,
232 lpFileName, -1, NULL, 0 );
234 lpFileNameW = (LPWSTR)_alloca( len * sizeof ( WCHAR ) );
236 if ( !len || !lpFileNameW )
238 FT_ERROR(( "FT_Stream_Open: cannot convert file name to LPWSTR\n" ));
239 return INVALID_HANDLE_VALUE;
242 /* now it is safe to do the translation */
243 MultiByteToWideChar( CP_ACP, MB_ERR_INVALID_CHARS,
244 lpFileName, -1, lpFileNameW, len );
247 return CreateFile2( lpFileNameW, dwDesiredAccess, dwShareMode,
248 dwCreationDisposition, &createExParams );
254 #if defined( _WIN32_WCE )
256 /* malloc.h provides implementation of alloca()/_alloca() */
259 FT_LOCAL_DEF( HANDLE )
260 CreateFileA( LPCSTR lpFileName,
261 DWORD dwDesiredAccess,
263 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
264 DWORD dwCreationDisposition,
265 DWORD dwFlagsAndAttributes,
266 HANDLE hTemplateFile )
272 /* allocate memory space for converted path name */
273 len = MultiByteToWideChar( CP_ACP, MB_ERR_INVALID_CHARS,
274 lpFileName, -1, NULL, 0 );
276 lpFileNameW = (LPWSTR)_alloca( len * sizeof ( WCHAR ) );
278 if ( !len || !lpFileNameW )
280 FT_ERROR(( "FT_Stream_Open: cannot convert file name to LPWSTR\n" ));
281 return INVALID_HANDLE_VALUE;
284 /* now it is safe to do the translation */
285 MultiByteToWideChar( CP_ACP, MB_ERR_INVALID_CHARS,
286 lpFileName, -1, lpFileNameW, len );
289 return CreateFileW( lpFileNameW, dwDesiredAccess, dwShareMode,
290 lpSecurityAttributes, dwCreationDisposition,
291 dwFlagsAndAttributes, hTemplateFile );
297 #if defined( _WIN32_WCE ) || defined ( _WIN32_WINDOWS ) || \
298 !defined( _WIN32_WINNT ) || _WIN32_WINNT <= 0x0400
301 GetFileSizeEx( HANDLE hFile,
302 PLARGE_INTEGER lpFileSize )
304 lpFileSize->u.LowPart = GetFileSize( hFile,
305 (DWORD *)&lpFileSize->u.HighPart );
307 if ( lpFileSize->u.LowPart == INVALID_FILE_SIZE &&
308 GetLastError() != NO_ERROR )
317 /* documentation is in ftobjs.h */
319 FT_BASE_DEF( FT_Error )
320 FT_Stream_Open( FT_Stream stream,
321 const char* filepathname )
329 return FT_THROW( Invalid_Stream_Handle );
332 file = CreateFileA( (LPCSTR)filepathname, GENERIC_READ, FILE_SHARE_READ,
333 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
334 if ( file == INVALID_HANDLE_VALUE )
336 FT_ERROR(( "FT_Stream_Open:" ));
337 FT_ERROR(( " could not open `%s'\n", filepathname ));
338 return FT_THROW( Cannot_Open_Resource );
341 if ( GetFileSizeEx( file, &size ) == FALSE )
343 FT_ERROR(( "FT_Stream_Open:" ));
344 FT_ERROR(( " could not retrieve size of file `%s'\n", filepathname ));
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 )
353 FT_ERROR(( "FT_Stream_Open: file is too big\n" ));
356 else if ( size.QuadPart == 0 )
358 FT_ERROR(( "FT_Stream_Open: zero-length file\n" ));
362 fm = CreateFileMapping( file, NULL, PAGE_READONLY, 0, 0, NULL );
365 FT_ERROR(( "FT_Stream_Open: can not map file\n" ));
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;
374 stream->base = (unsigned char *)
375 MapViewOfFile( fm, FILE_MAP_READ, 0, 0, 0 );
379 if ( stream->base != NULL )
380 stream->close = ft_close_stream_by_munmap;
383 DWORD total_read_count;
386 FT_ERROR(( "FT_Stream_Open:" ));
387 FT_ERROR(( " could not `mmap' file `%s'\n", filepathname ));
389 stream->base = (unsigned char*)ft_alloc( stream->memory, stream->size );
393 FT_ERROR(( "FT_Stream_Open:" ));
394 FT_ERROR(( " could not `alloc' memory\n" ));
398 total_read_count = 0;
405 stream->base + total_read_count,
406 stream->size - total_read_count,
407 &read_count, NULL ) == FALSE )
409 FT_ERROR(( "FT_Stream_Open:" ));
410 FT_ERROR(( " error while `read'ing file `%s'\n", filepathname ));
414 total_read_count += read_count;
416 } while ( total_read_count != stream->size );
418 stream->close = ft_close_stream_by_free;
423 stream->descriptor.pointer = stream->base;
424 stream->pathname.pointer = (char*)filepathname;
428 FT_TRACE1(( "FT_Stream_Open:" ));
429 FT_TRACE1(( " opened `%s' (%ld bytes) successfully\n",
430 filepathname, stream->size ));
435 ft_free( stream->memory, stream->base );
444 return FT_THROW( Cannot_Open_Stream );
448 #ifdef FT_DEBUG_MEMORY
451 ft_mem_debug_init( FT_Memory memory );
454 ft_mem_debug_done( FT_Memory memory );
459 /* documentation is in ftobjs.h */
461 FT_BASE_DEF( FT_Memory )
462 FT_New_Memory( void )
468 heap = GetProcessHeap();
469 memory = heap ? (FT_Memory)HeapAlloc( heap, 0, sizeof ( *memory ) )
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 );
487 /* documentation is in ftobjs.h */
490 FT_Done_Memory( FT_Memory memory )
492 #ifdef FT_DEBUG_MEMORY
493 ft_mem_debug_done( memory );
495 memory->free( memory, memory );