ReactOS  0.4.13-dev-92-gf251225
font.c
Go to the documentation of this file.
1 /*
2  * Implementation of the Microsoft Installer (msi.dll)
3  *
4  * Copyright 2004,2005 Aric Stewart for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include <stdarg.h>
22 #include "windef.h"
23 #include "winbase.h"
24 #include "winerror.h"
25 #include "winreg.h"
26 #include "wine/debug.h"
27 #include "msipriv.h"
28 #include "wine/unicode.h"
29 
31 
32 typedef struct _tagTT_OFFSET_TABLE {
40 
41 typedef struct _tagTT_TABLE_DIRECTORY {
42  char szTag[4]; /* table name */
43  ULONG uCheckSum; /* Check sum */
44  ULONG uOffset; /* Offset from beginning of file */
45  ULONG uLength; /* length of the table in bytes */
47 
48 typedef struct _tagTT_NAME_TABLE_HEADER {
49  USHORT uFSelector; /* format selector. Always 0 */
50  USHORT uNRCount; /* Name Records count */
51  USHORT uStorageOffset; /* Offset for strings storage,
52  * from start of the table */
54 
55 #define NAME_ID_FULL_FONT_NAME 4
56 #define NAME_ID_VERSION 5
57 
58 typedef struct _tagTT_NAME_RECORD {
64  USHORT uStringOffset; /* from start of storage area */
66 
67 #define SWAPWORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
68 #define SWAPLONG(x) MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x)))
69 
70 static const WCHAR regfont1[] =
71  {'S','o','f','t','w','a','r','e','\\',
72  'M','i','c','r','o','s','o','f','t','\\',
73  'W','i','n','d','o','w','s',' ','N','T','\\',
74  'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
75  'F','o','n','t','s',0};
76 static const WCHAR regfont2[] =
77  {'S','o','f','t','w','a','r','e','\\',
78  'M','i','c','r','o','s','o','f','t','\\',
79  'W','i','n','d','o','w','s','\\',
80  'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
81  'F','o','n','t','s',0};
82 
83 /*
84  * Code based off of code located here
85  * http://www.codeproject.com/gdi/fontnamefromfile.asp
86  */
87 static WCHAR *load_ttf_name_id( const WCHAR *filename, DWORD id )
88 {
89  TT_TABLE_DIRECTORY tblDir;
90  BOOL bFound = FALSE;
91  TT_OFFSET_TABLE ttOffsetTable;
92  TT_NAME_TABLE_HEADER ttNTHeader;
93  TT_NAME_RECORD ttRecord;
94  DWORD dwRead;
95  HANDLE handle;
96  LPWSTR ret = NULL;
97  int i;
98 
102  {
103  ERR("Unable to open font file %s\n", debugstr_w(filename));
104  return NULL;
105  }
106 
107  if (!ReadFile(handle,&ttOffsetTable, sizeof(TT_OFFSET_TABLE),&dwRead,NULL))
108  goto end;
109 
110  ttOffsetTable.uNumOfTables = SWAPWORD(ttOffsetTable.uNumOfTables);
111  ttOffsetTable.uMajorVersion = SWAPWORD(ttOffsetTable.uMajorVersion);
112  ttOffsetTable.uMinorVersion = SWAPWORD(ttOffsetTable.uMinorVersion);
113 
114  if ((ttOffsetTable.uMajorVersion != 1 || ttOffsetTable.uMinorVersion != 0) &&
115  (ttOffsetTable.uMajorVersion != 0x4f54 || ttOffsetTable.uMinorVersion != 0x544f))
116  goto end;
117 
118  for (i=0; i< ttOffsetTable.uNumOfTables; i++)
119  {
120  if (!ReadFile(handle,&tblDir, sizeof(TT_TABLE_DIRECTORY),&dwRead,NULL))
121  break;
122  if (memcmp(tblDir.szTag,"name",4)==0)
123  {
124  bFound = TRUE;
125  tblDir.uLength = SWAPLONG(tblDir.uLength);
126  tblDir.uOffset = SWAPLONG(tblDir.uOffset);
127  break;
128  }
129  }
130 
131  if (!bFound)
132  goto end;
133 
135  if (!ReadFile(handle,&ttNTHeader, sizeof(TT_NAME_TABLE_HEADER), &dwRead,NULL))
136  goto end;
137 
138  ttNTHeader.uNRCount = SWAPWORD(ttNTHeader.uNRCount);
139  ttNTHeader.uStorageOffset = SWAPWORD(ttNTHeader.uStorageOffset);
140  for(i=0; i<ttNTHeader.uNRCount; i++)
141  {
142  if (!ReadFile(handle,&ttRecord, sizeof(TT_NAME_RECORD),&dwRead,NULL))
143  break;
144 
145  ttRecord.uNameID = SWAPWORD(ttRecord.uNameID);
146  ttRecord.uPlatformID = SWAPWORD(ttRecord.uPlatformID);
147  ttRecord.uEncodingID = SWAPWORD(ttRecord.uEncodingID);
148  if (ttRecord.uNameID == id && ttRecord.uPlatformID == 3 &&
149  (ttRecord.uEncodingID == 0 || ttRecord.uEncodingID == 1))
150  {
151  WCHAR *buf;
152  unsigned int i;
153 
154  ttRecord.uStringLength = SWAPWORD(ttRecord.uStringLength);
155  ttRecord.uStringOffset = SWAPWORD(ttRecord.uStringOffset);
156  SetFilePointer(handle, tblDir.uOffset + ttRecord.uStringOffset + ttNTHeader.uStorageOffset,
157  NULL, FILE_BEGIN);
158  if (!(buf = msi_alloc_zero( ttRecord.uStringLength + sizeof(WCHAR) ))) goto end;
159  dwRead = 0;
160  ReadFile(handle, buf, ttRecord.uStringLength, &dwRead, NULL);
161  if (dwRead % sizeof(WCHAR))
162  {
163  msi_free(buf);
164  goto end;
165  }
166  for (i = 0; i < dwRead / sizeof(WCHAR); i++) buf[i] = SWAPWORD(buf[i]);
167  ret = strdupW(buf);
168  msi_free(buf);
169  break;
170  }
171  }
172 
173 end:
175  return ret;
176 }
177 
179 {
180  static const WCHAR truetypeW[] = {' ','(','T','r','u','e','T','y','p','e',')',0};
181  WCHAR *name, *ret = NULL;
182 
184  {
185  if (!name[0])
186  {
187  WARN("empty font name\n");
188  msi_free( name );
189  return NULL;
190  }
191  ret = msi_alloc( (strlenW( name ) + strlenW( truetypeW ) + 1 ) * sizeof(WCHAR) );
192  strcpyW( ret, name );
193  strcatW( ret, truetypeW );
194  msi_free( name );
195  }
196  return ret;
197 }
198 
200 {
201  static const WCHAR fmtW[] = {'%','u','.','%','u','.','0','.','0',0};
202  WCHAR *version, *p, *q, *ret = NULL;
203 
205  {
206  int len, major = 0, minor = 0;
207  if ((p = strchrW( version, ';' ))) *p = 0;
208  p = version;
209  while (*p && !isdigitW( *p )) p++;
210  if ((q = strchrW( p, '.' )))
211  {
212  major = atoiW( p );
213  p = ++q;
214  while (*q && isdigitW( *q )) q++;
215  if (!*q || *q == ' ') minor = atoiW( p );
216  else major = 0;
217  }
218  len = strlenW( fmtW ) + 20;
219  ret = msi_alloc( len * sizeof(WCHAR) );
220  sprintfW( ret, fmtW, major, minor );
221  msi_free( version );
222  }
223  return ret;
224 }
225 
227 {
228  MSIPACKAGE *package = param;
229  LPWSTR name;
231  MSIFILE *file;
232  MSICOMPONENT *comp;
233  HKEY hkey1, hkey2;
234  MSIRECORD *uirow;
235  LPWSTR uipath, p;
236 
238  file = msi_get_loaded_file( package, filename );
239  if (!file)
240  {
241  WARN("unable to find file %s\n", debugstr_w(filename));
242  return ERROR_SUCCESS;
243  }
244  comp = msi_get_loaded_component( package, file->Component->Component );
245  if (!comp)
246  {
247  WARN("unable to find component %s\n", debugstr_w(file->Component->Component));
248  return ERROR_SUCCESS;
249  }
250  comp->Action = msi_get_component_action( package, comp );
251  if (comp->Action != INSTALLSTATE_LOCAL)
252  {
253  TRACE("component not scheduled for installation %s\n", debugstr_w(comp->Component));
254  return ERROR_SUCCESS;
255  }
256 
259 
260  if (MSI_RecordIsNull(row,2))
261  name = font_name_from_file( file->TargetPath );
262  else
264 
265  if (name)
266  {
267  msi_reg_set_val_str( hkey1, name, file->TargetPath);
268  msi_reg_set_val_str( hkey2, name, file->TargetPath);
269  }
270 
271  msi_free(name);
272  RegCloseKey(hkey1);
273  RegCloseKey(hkey2);
274 
275  /* the UI chunk */
276  uirow = MSI_CreateRecord( 1 );
277  uipath = strdupW( file->TargetPath );
278  p = strrchrW(uipath,'\\');
279  if (p) p++;
280  else p = uipath;
281  MSI_RecordSetStringW( uirow, 1, p );
283  msiobj_release( &uirow->hdr );
284  msi_free( uipath );
285  /* FIXME: call msi_ui_progress? */
286 
287  return ERROR_SUCCESS;
288 }
289 
291 {
292  static const WCHAR query[] = {
293  'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','`','F','o','n','t','`',0};
294  MSIQUERY *view;
295  UINT rc;
296 
297  rc = MSI_DatabaseOpenViewW(package->db, query, &view);
298  if (rc != ERROR_SUCCESS)
299  return ERROR_SUCCESS;
300 
302  msiobj_release(&view->hdr);
303  return rc;
304 }
305 
307 {
308  MSIPACKAGE *package = param;
309  LPWSTR name;
311  MSIFILE *file;
312  MSICOMPONENT *comp;
313  HKEY hkey1, hkey2;
314  MSIRECORD *uirow;
315  LPWSTR uipath, p;
316 
318  file = msi_get_loaded_file( package, filename );
319  if (!file)
320  {
321  WARN("unable to find file %s\n", debugstr_w(filename));
322  return ERROR_SUCCESS;
323  }
324  comp = msi_get_loaded_component( package, file->Component->Component );
325  if (!comp)
326  {
327  WARN("unable to find component %s\n", debugstr_w(file->Component->Component));
328  return ERROR_SUCCESS;
329  }
330  comp->Action = msi_get_component_action( package, comp );
331  if (comp->Action != INSTALLSTATE_ABSENT)
332  {
333  TRACE("component not scheduled for removal %s\n", debugstr_w(comp->Component));
334  return ERROR_SUCCESS;
335  }
336 
339 
340  if (MSI_RecordIsNull( row, 2 ))
341  name = font_name_from_file( file->TargetPath );
342  else
343  name = msi_dup_record_field( row, 2 );
344 
345  if (name)
346  {
347  RegDeleteValueW( hkey1, name );
348  RegDeleteValueW( hkey2, name );
349  }
350 
351  msi_free( name );
352  RegCloseKey( hkey1 );
353  RegCloseKey( hkey2 );
354 
355  /* the UI chunk */
356  uirow = MSI_CreateRecord( 1 );
357  uipath = strdupW( file->TargetPath );
358  p = strrchrW( uipath,'\\' );
359  if (p) p++;
360  else p = uipath;
361  MSI_RecordSetStringW( uirow, 1, p );
363  msiobj_release( &uirow->hdr );
364  msi_free( uipath );
365  /* FIXME: call msi_ui_progress? */
366 
367  return ERROR_SUCCESS;
368 }
369 
371 {
372  static const WCHAR query[] = {
373  'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','`','F','o','n','t','`',0};
374  MSIQUERY *view;
375  UINT r;
376 
377  r = MSI_DatabaseOpenViewW( package->db, query, &view );
378  if (r != ERROR_SUCCESS)
379  return ERROR_SUCCESS;
380 
382  msiobj_release( &view->hdr );
383  return r;
384 }
UINT ACTION_UnregisterFonts(MSIPACKAGE *package)
Definition: font.c:370
struct _tagTT_OFFSET_TABLE TT_OFFSET_TABLE
static UINT ITERATE_RegisterFonts(MSIRECORD *row, LPVOID param)
Definition: font.c:226
USHORT uRangeShift
Definition: font.c:38
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
Definition: sock.c:82
#define TRUE
Definition: types.h:120
UINT MSI_RecordSetStringW(MSIRECORD *, UINT, LPCWSTR) DECLSPEC_HIDDEN
Definition: record.c:649
#define CloseHandle
Definition: compat.h:398
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
#define ERROR_SUCCESS
Definition: deptool.c:10
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
static WCHAR * strdupW(const WCHAR *src)
Definition: main.c:92
MSIOBJECTHDR hdr
Definition: msipriv.h:141
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
WINE_UNICODE_INLINE WCHAR * strchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:248
USHORT uStorageOffset
Definition: font.c:51
#define WARN(fmt,...)
Definition: debug.h:111
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
GLuint GLuint end
Definition: gl.h:1545
INSTALLSTATE Action
Definition: msipriv.h:510
INSTALLSTATE msi_get_component_action(MSIPACKAGE *package, MSICOMPONENT *comp)
Definition: action.c:755
USHORT uStringLength
Definition: font.c:63
const char * filename
Definition: ioapi.h:135
WCHAR * msi_font_version_from_file(const WCHAR *filename)
Definition: font.c:199
static void * msi_alloc_zero(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1210
WINE_DEFAULT_DEBUG_CHANNEL(d3dx)
DWORD WINAPI DECLSPEC_HOTPATCH SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod)
Definition: fileinfo.c:204
static WCHAR * font_name_from_file(const WCHAR *filename)
Definition: font.c:178
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static const WCHAR regfont2[]
Definition: font.c:76
#define NAME_ID_VERSION
Definition: font.c:56
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
static UINT ITERATE_UnregisterFonts(MSIRECORD *row, LPVOID param)
Definition: font.c:306
USHORT uStringOffset
Definition: font.c:64
USHORT uNumOfTables
Definition: font.c:35
unsigned int BOOL
Definition: ntddk_ex.h:94
BOOL MSI_RecordIsNull(MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:369
#define debugstr_w
Definition: kernel32.h:32
INT MSI_ProcessMessage(MSIPACKAGE *, INSTALLMESSAGE, MSIRECORD *) DECLSPEC_HIDDEN
Definition: package.c:1946
#define SWAPWORD(x)
Definition: font.c:67
smooth NULL
Definition: ftsmooth.c:416
static const WCHAR version[]
Definition: asmname.c:64
USHORT uLanguageID
Definition: font.c:61
LONG msi_reg_set_val_str(HKEY hkey, LPCWSTR name, LPCWSTR value) DECLSPEC_HIDDEN
Definition: registry.c:360
const WCHAR * MSI_RecordGetString(const MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:482
USHORT uNameID
Definition: font.c:62
#define OPEN_EXISTING
Definition: compat.h:426
#define NAME_ID_FULL_FONT_NAME
Definition: font.c:55
MSIFILE * msi_get_loaded_file(MSIPACKAGE *package, const WCHAR *key)
Definition: action.c:674
struct _tagTT_TABLE_DIRECTORY TT_TABLE_DIRECTORY
#define TRACE(s)
Definition: solgame.cpp:4
__wchar_t WCHAR
Definition: xmlstorage.h:180
GLfloat param
Definition: glext.h:5796
const char file[]
Definition: icontest.c:11
USHORT uPlatformID
Definition: font.c:59
unsigned long DWORD
Definition: ntddk_ex.h:95
MSIDATABASE * db
Definition: msipriv.h:386
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
int msiobj_release(MSIOBJECTHDR *info)
Definition: handle.c:242
LPWSTR Component
Definition: msipriv.h:502
MSICOMPONENT * msi_get_loaded_component(MSIPACKAGE *package, const WCHAR *Component)
Definition: action.c:652
static const WCHAR regfont1[]
Definition: font.c:70
int ret
MSIRECORD * MSI_CreateRecord(UINT) DECLSPEC_HIDDEN
Definition: record.c:79
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
UINT ACTION_RegisterFonts(MSIPACKAGE *package)
Definition: font.c:290
USHORT uEncodingID
Definition: font.c:60
GLenum GLsizei len
Definition: glext.h:6722
LONG WINAPI RegCreateKeyW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:1202
#define GENERIC_READ
Definition: compat.h:124
WINE_UNICODE_INLINE WCHAR * strrchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:254
#define ERR(fmt,...)
Definition: debug.h:109
#define SWAPLONG(x)
Definition: font.c:68
#define FILE_BEGIN
Definition: winbase.h:112
WINE_UNICODE_INLINE WCHAR * strcpyW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:219
USHORT uMinorVersion
Definition: font.c:34
LONG WINAPI RegDeleteValueW(HKEY hKey, LPCWSTR lpValueName)
Definition: reg.c:2368
unsigned short USHORT
Definition: pedump.c:61
WCHAR * msi_dup_record_field(MSIRECORD *row, INT index) DECLSPEC_HIDDEN
Definition: record.c:1055
#define major(rdev)
Definition: propsheet.cpp:879
#define sprintfW
Definition: unicode.h:58
WINE_UNICODE_INLINE WCHAR * strcatW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:242
WINE_UNICODE_INLINE int isdigitW(WCHAR wc)
Definition: unicode.h:170
struct _tagTT_NAME_RECORD TT_NAME_RECORD
USHORT uMajorVersion
Definition: font.c:33
unsigned int UINT
Definition: ndis.h:50
static WCHAR * load_ttf_name_id(const WCHAR *filename, DWORD id)
Definition: font.c:87
#define CreateFileW
Definition: compat.h:400
static BOOL msi_free(void *mem)
Definition: msipriv.h:1227
USHORT uSearchRange
Definition: font.c:36
Definition: name.c:36
static void * msi_alloc(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1204
unsigned int ULONG
Definition: retypes.h:1
#define minor(rdev)
Definition: propsheet.cpp:880
static IOleDocumentView * view
Definition: activex.c:1749
GLfloat GLfloat p
Definition: glext.h:8902
WCHAR * LPWSTR
Definition: xmlstorage.h:184
USHORT uEntrySelector
Definition: font.c:37
UINT MSI_IterateRecords(MSIQUERY *, LPDWORD, record_func, LPVOID) DECLSPEC_HIDDEN
Definition: msiquery.c:168
BOOL WINAPI ReadFile(IN HANDLE hFile, IN LPVOID lpBuffer, IN DWORD nNumberOfBytesToRead, OUT LPDWORD lpNumberOfBytesRead OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:123
struct _tagTT_NAME_TABLE_HEADER TT_NAME_TABLE_HEADER
WINE_UNICODE_INLINE int atoiW(const WCHAR *str)
Definition: unicode.h:315
struct png_info_def *typedef unsigned char **typedef struct png_info_def *typedef struct png_info_def *typedef struct png_info_def *typedef unsigned char ** row
Definition: typeof.h:78
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
Definition: fci.c:126
UINT MSI_DatabaseOpenViewW(MSIDATABASE *, LPCWSTR, MSIQUERY **) DECLSPEC_HIDDEN
Definition: msiquery.c:111
GLuint const GLchar * name
Definition: glext.h:6031