ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

font.c
Go to the documentation of this file.
00001 /*
00002  * Implementation of the Microsoft Installer (msi.dll)
00003  *
00004  * Copyright 2004,2005 Aric Stewart for CodeWeavers
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 #include <stdarg.h>
00022 #include "windef.h"
00023 #include "winbase.h"
00024 #include "winerror.h"
00025 #include "winreg.h"
00026 #include "wine/debug.h"
00027 #include "msipriv.h"
00028 #include "wine/unicode.h"
00029 
00030 WINE_DEFAULT_DEBUG_CHANNEL(msi);
00031 
00032 typedef struct _tagTT_OFFSET_TABLE {
00033     USHORT uMajorVersion;
00034     USHORT uMinorVersion;
00035     USHORT uNumOfTables;
00036     USHORT uSearchRange;
00037     USHORT uEntrySelector;
00038     USHORT uRangeShift;
00039 } TT_OFFSET_TABLE;
00040 
00041 typedef struct _tagTT_TABLE_DIRECTORY {
00042     char szTag[4]; /* table name */
00043     ULONG uCheckSum; /* Check sum */
00044     ULONG uOffset; /* Offset from beginning of file */
00045     ULONG uLength; /* length of the table in bytes */
00046 } TT_TABLE_DIRECTORY;
00047 
00048 typedef struct _tagTT_NAME_TABLE_HEADER {
00049     USHORT uFSelector; /* format selector. Always 0 */
00050     USHORT uNRCount; /* Name Records count */
00051     USHORT uStorageOffset; /* Offset for strings storage,
00052                             * from start of the table */
00053 } TT_NAME_TABLE_HEADER;
00054 
00055 #define NAME_ID_FULL_FONT_NAME  4
00056 #define NAME_ID_VERSION         5
00057 
00058 typedef struct _tagTT_NAME_RECORD {
00059     USHORT uPlatformID;
00060     USHORT uEncodingID;
00061     USHORT uLanguageID;
00062     USHORT uNameID;
00063     USHORT uStringLength;
00064     USHORT uStringOffset; /* from start of storage area */
00065 } TT_NAME_RECORD;
00066 
00067 #define SWAPWORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
00068 #define SWAPLONG(x) MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x)))
00069 
00070 static const WCHAR regfont1[] =
00071     {'S','o','f','t','w','a','r','e','\\',
00072      'M','i','c','r','o','s','o','f','t','\\',
00073      'W','i','n','d','o','w','s',' ','N','T','\\',
00074      'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00075      'F','o','n','t','s',0};
00076 static const WCHAR regfont2[] =
00077     {'S','o','f','t','w','a','r','e','\\',
00078      'M','i','c','r','o','s','o','f','t','\\',
00079      'W','i','n','d','o','w','s','\\',
00080      'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00081      'F','o','n','t','s',0};
00082 
00083 /*
00084  * Code based off of code located here
00085  * http://www.codeproject.com/gdi/fontnamefromfile.asp
00086  */
00087 static WCHAR *load_ttf_name_id( const WCHAR *filename, DWORD id )
00088 {
00089     TT_TABLE_DIRECTORY tblDir;
00090     BOOL bFound = FALSE;
00091     TT_OFFSET_TABLE ttOffsetTable;
00092     TT_NAME_TABLE_HEADER ttNTHeader;
00093     TT_NAME_RECORD ttRecord;
00094     DWORD dwRead;
00095     HANDLE handle;
00096     LPWSTR ret = NULL;
00097     int i;
00098 
00099     handle = CreateFileW(filename ,GENERIC_READ, 0, NULL, OPEN_EXISTING,
00100                     FILE_ATTRIBUTE_NORMAL, 0 );
00101     if (handle == INVALID_HANDLE_VALUE)
00102     {
00103         ERR("Unable to open font file %s\n", debugstr_w(filename));
00104         return NULL;
00105     }
00106 
00107     if (!ReadFile(handle,&ttOffsetTable, sizeof(TT_OFFSET_TABLE),&dwRead,NULL))
00108         goto end;
00109 
00110     ttOffsetTable.uNumOfTables = SWAPWORD(ttOffsetTable.uNumOfTables);
00111     ttOffsetTable.uMajorVersion = SWAPWORD(ttOffsetTable.uMajorVersion);
00112     ttOffsetTable.uMinorVersion = SWAPWORD(ttOffsetTable.uMinorVersion);
00113 
00114     if ((ttOffsetTable.uMajorVersion != 1 || ttOffsetTable.uMinorVersion != 0) &&
00115         (ttOffsetTable.uMajorVersion != 0x4f54 || ttOffsetTable.uMinorVersion != 0x544f))
00116         goto end;
00117 
00118     for (i=0; i< ttOffsetTable.uNumOfTables; i++)
00119     {
00120         if (!ReadFile(handle,&tblDir, sizeof(TT_TABLE_DIRECTORY),&dwRead,NULL))
00121             break;
00122         if (memcmp(tblDir.szTag,"name",4)==0)
00123         {
00124             bFound = TRUE;
00125             tblDir.uLength = SWAPLONG(tblDir.uLength);
00126             tblDir.uOffset = SWAPLONG(tblDir.uOffset);
00127             break;
00128         }
00129     }
00130 
00131     if (!bFound)
00132         goto end;
00133 
00134     SetFilePointer(handle, tblDir.uOffset, NULL, FILE_BEGIN);
00135     if (!ReadFile(handle,&ttNTHeader, sizeof(TT_NAME_TABLE_HEADER), &dwRead,NULL))
00136         goto end;
00137 
00138     ttNTHeader.uNRCount = SWAPWORD(ttNTHeader.uNRCount);
00139     ttNTHeader.uStorageOffset = SWAPWORD(ttNTHeader.uStorageOffset);
00140     for(i=0; i<ttNTHeader.uNRCount; i++)
00141     {
00142         if (!ReadFile(handle,&ttRecord, sizeof(TT_NAME_RECORD),&dwRead,NULL))
00143             break;
00144 
00145         ttRecord.uNameID = SWAPWORD(ttRecord.uNameID);
00146         ttRecord.uPlatformID = SWAPWORD(ttRecord.uPlatformID);
00147         ttRecord.uEncodingID = SWAPWORD(ttRecord.uEncodingID);
00148         if (ttRecord.uNameID == id && ttRecord.uPlatformID == 3 &&
00149             (ttRecord.uEncodingID == 0 || ttRecord.uEncodingID == 1))
00150         {
00151             WCHAR *buf;
00152             unsigned int i;
00153 
00154             ttRecord.uStringLength = SWAPWORD(ttRecord.uStringLength);
00155             ttRecord.uStringOffset = SWAPWORD(ttRecord.uStringOffset);
00156             SetFilePointer(handle, tblDir.uOffset + ttRecord.uStringOffset + ttNTHeader.uStorageOffset,
00157                            NULL, FILE_BEGIN);
00158             if (!(buf = msi_alloc_zero( ttRecord.uStringLength + sizeof(WCHAR) ))) goto end;
00159             dwRead = 0;
00160             ReadFile(handle, buf, ttRecord.uStringLength, &dwRead, NULL);
00161             if (dwRead % sizeof(WCHAR))
00162             {
00163                 msi_free(buf);
00164                 goto end;
00165             }
00166             for (i = 0; i < dwRead / sizeof(WCHAR); i++) buf[i] = SWAPWORD(buf[i]);
00167             ret = strdupW(buf);
00168             msi_free(buf);
00169             break;
00170         }
00171     }
00172 
00173 end:
00174     CloseHandle(handle);
00175     TRACE("Returning %s\n", debugstr_w(ret));
00176     return ret;
00177 }
00178 
00179 static WCHAR *font_name_from_file( const WCHAR *filename )
00180 {
00181     static const WCHAR truetypeW[] = {' ','(','T','r','u','e','T','y','p','e',')',0};
00182     WCHAR *name, *ret = NULL;
00183 
00184     if ((name = load_ttf_name_id( filename, NAME_ID_FULL_FONT_NAME )))
00185     {
00186         if (!name[0])
00187         {
00188             WARN("empty font name\n");
00189             msi_free( name );
00190             return NULL;
00191         }
00192         ret = msi_alloc( (strlenW( name ) + strlenW( truetypeW ) + 1 ) * sizeof(WCHAR) );
00193         strcpyW( ret, name );
00194         strcatW( ret, truetypeW );
00195         msi_free( name );
00196     }
00197     return ret;
00198 }
00199 
00200 WCHAR *msi_font_version_from_file( const WCHAR *filename )
00201 {
00202     static const WCHAR fmtW[] = {'%','u','.','%','u','.','0','.','0',0};
00203     WCHAR *version, *p, *q, *ret = NULL;
00204 
00205     if ((version = load_ttf_name_id( filename, NAME_ID_VERSION )))
00206     {
00207         int len, major = 0, minor = 0;
00208         if ((p = strchrW( version, ';' ))) *p = 0;
00209         p = version;
00210         while (*p && !isdigitW( *p )) p++;
00211         if ((q = strchrW( p, '.' )))
00212         {
00213             major = atoiW( p );
00214             p = ++q;
00215             while (*q && isdigitW( *q )) q++;
00216             if (!*q || *q == ' ') minor = atoiW( p );
00217             else major = 0;
00218         }
00219         len = strlenW( fmtW ) + 20;
00220         ret = msi_alloc( len * sizeof(WCHAR) );
00221         sprintfW( ret, fmtW, major, minor );
00222         msi_free( version );
00223     }
00224     return ret;
00225 }
00226 
00227 static UINT ITERATE_RegisterFonts(MSIRECORD *row, LPVOID param)
00228 {
00229     MSIPACKAGE *package = param;
00230     LPWSTR name;
00231     LPCWSTR filename;
00232     MSIFILE *file;
00233     MSICOMPONENT *comp;
00234     HKEY hkey1, hkey2;
00235     MSIRECORD *uirow;
00236     LPWSTR uipath, p;
00237 
00238     filename = MSI_RecordGetString( row, 1 );
00239     file = msi_get_loaded_file( package, filename );
00240     if (!file)
00241     {
00242         WARN("unable to find file %s\n", debugstr_w(filename));
00243         return ERROR_SUCCESS;
00244     }
00245     comp = msi_get_loaded_component( package, file->Component->Component );
00246     if (!comp)
00247     {
00248         WARN("unable to find component %s\n", debugstr_w(file->Component->Component));
00249         return ERROR_SUCCESS;
00250     }
00251     comp->Action = msi_get_component_action( package, comp );
00252     if (comp->Action != INSTALLSTATE_LOCAL)
00253     {
00254         TRACE("component not scheduled for installation %s\n", debugstr_w(comp->Component));
00255         return ERROR_SUCCESS;
00256     }
00257 
00258     RegCreateKeyW(HKEY_LOCAL_MACHINE,regfont1,&hkey1);
00259     RegCreateKeyW(HKEY_LOCAL_MACHINE,regfont2,&hkey2);
00260 
00261     if (MSI_RecordIsNull(row,2))
00262         name = font_name_from_file( file->TargetPath );
00263     else
00264         name = msi_dup_record_field(row,2);
00265 
00266     if (name)
00267     {
00268         msi_reg_set_val_str( hkey1, name, file->TargetPath);
00269         msi_reg_set_val_str( hkey2, name, file->TargetPath);
00270     }
00271 
00272     msi_free(name);
00273     RegCloseKey(hkey1);
00274     RegCloseKey(hkey2);
00275 
00276     /* the UI chunk */
00277     uirow = MSI_CreateRecord( 1 );
00278     uipath = strdupW( file->TargetPath );
00279     p = strrchrW(uipath,'\\');
00280     if (p) p++;
00281     else p = uipath;
00282     MSI_RecordSetStringW( uirow, 1, p );
00283     msi_ui_actiondata( package, szRegisterFonts, uirow );
00284     msiobj_release( &uirow->hdr );
00285     msi_free( uipath );
00286     /* FIXME: call msi_ui_progress? */
00287 
00288     return ERROR_SUCCESS;
00289 }
00290 
00291 UINT ACTION_RegisterFonts(MSIPACKAGE *package)
00292 {
00293     static const WCHAR query[] = {
00294         'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','`','F','o','n','t','`',0};
00295     MSIQUERY *view;
00296     UINT rc;
00297 
00298     rc = MSI_DatabaseOpenViewW(package->db, query, &view);
00299     if (rc != ERROR_SUCCESS)
00300         return ERROR_SUCCESS;
00301 
00302     rc = MSI_IterateRecords(view, NULL, ITERATE_RegisterFonts, package);
00303     msiobj_release(&view->hdr);
00304     return rc;
00305 }
00306 
00307 static UINT ITERATE_UnregisterFonts( MSIRECORD *row, LPVOID param )
00308 {
00309     MSIPACKAGE *package = param;
00310     LPWSTR name;
00311     LPCWSTR filename;
00312     MSIFILE *file;
00313     MSICOMPONENT *comp;
00314     HKEY hkey1, hkey2;
00315     MSIRECORD *uirow;
00316     LPWSTR uipath, p;
00317 
00318     filename = MSI_RecordGetString( row, 1 );
00319     file = msi_get_loaded_file( package, filename );
00320     if (!file)
00321     {
00322         WARN("unable to find file %s\n", debugstr_w(filename));
00323         return ERROR_SUCCESS;
00324     }
00325     comp = msi_get_loaded_component( package, file->Component->Component );
00326     if (!comp)
00327     {
00328         WARN("unable to find component %s\n", debugstr_w(file->Component->Component));
00329         return ERROR_SUCCESS;
00330     }
00331     comp->Action = msi_get_component_action( package, comp );
00332     if (comp->Action != INSTALLSTATE_ABSENT)
00333     {
00334         TRACE("component not scheduled for removal %s\n", debugstr_w(comp->Component));
00335         return ERROR_SUCCESS;
00336     }
00337 
00338     RegCreateKeyW( HKEY_LOCAL_MACHINE, regfont1, &hkey1 );
00339     RegCreateKeyW( HKEY_LOCAL_MACHINE, regfont2, &hkey2 );
00340 
00341     if (MSI_RecordIsNull( row, 2 ))
00342         name = font_name_from_file( file->TargetPath );
00343     else
00344         name = msi_dup_record_field( row, 2 );
00345 
00346     if (name)
00347     {
00348         RegDeleteValueW( hkey1, name );
00349         RegDeleteValueW( hkey2, name );
00350     }
00351 
00352     msi_free( name );
00353     RegCloseKey( hkey1 );
00354     RegCloseKey( hkey2 );
00355 
00356     /* the UI chunk */
00357     uirow = MSI_CreateRecord( 1 );
00358     uipath = strdupW( file->TargetPath );
00359     p = strrchrW( uipath,'\\' );
00360     if (p) p++;
00361     else p = uipath;
00362     MSI_RecordSetStringW( uirow, 1, p );
00363     msi_ui_actiondata( package, szUnregisterFonts, uirow );
00364     msiobj_release( &uirow->hdr );
00365     msi_free( uipath );
00366     /* FIXME: call msi_ui_progress? */
00367 
00368     return ERROR_SUCCESS;
00369 }
00370 
00371 UINT ACTION_UnregisterFonts( MSIPACKAGE *package )
00372 {
00373     static const WCHAR query[] = {
00374         'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','`','F','o','n','t','`',0};
00375     MSIQUERY *view;
00376     UINT r;
00377 
00378     r = MSI_DatabaseOpenViewW( package->db, query, &view );
00379     if (r != ERROR_SUCCESS)
00380         return ERROR_SUCCESS;
00381 
00382     r = MSI_IterateRecords( view, NULL, ITERATE_UnregisterFonts, package );
00383     msiobj_release( &view->hdr );
00384     return r;
00385 }

Generated on Fri May 25 2012 04:18:59 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.