Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfont.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
1.7.6.1
|