xref: /reactos/dll/win32/msi/font.c (revision f4be6dc3)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * Implementation of the Microsoft Installer (msi.dll)
3c2c66affSColin Finck  *
4c2c66affSColin Finck  * Copyright 2004,2005 Aric Stewart for CodeWeavers
5c2c66affSColin Finck  *
6c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
7c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
8c2c66affSColin Finck  * License as published by the Free Software Foundation; either
9c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
10c2c66affSColin Finck  *
11c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
12c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14c2c66affSColin Finck  * Lesser General Public License for more details.
15c2c66affSColin Finck  *
16c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
17c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
18c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19c2c66affSColin Finck  */
20c2c66affSColin Finck 
21c42b133eSAmine Khaldi #include <stdarg.h>
22c42b133eSAmine Khaldi #include "windef.h"
23c42b133eSAmine Khaldi #include "winbase.h"
24c42b133eSAmine Khaldi #include "winerror.h"
25c42b133eSAmine Khaldi #include "winreg.h"
26c42b133eSAmine Khaldi #include "wine/debug.h"
27c2c66affSColin Finck #include "msipriv.h"
28c2c66affSColin Finck 
29c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(msi);
30c2c66affSColin Finck 
31*f4be6dc3SMikhail struct offset_table
32*f4be6dc3SMikhail {
33c2c66affSColin Finck     USHORT uMajorVersion;
34c2c66affSColin Finck     USHORT uMinorVersion;
35c2c66affSColin Finck     USHORT uNumOfTables;
36c2c66affSColin Finck     USHORT uSearchRange;
37c2c66affSColin Finck     USHORT uEntrySelector;
38c2c66affSColin Finck     USHORT uRangeShift;
39*f4be6dc3SMikhail };
40c2c66affSColin Finck 
41*f4be6dc3SMikhail struct table_directory
42*f4be6dc3SMikhail {
43c2c66affSColin Finck     char szTag[4]; /* table name */
44c2c66affSColin Finck     ULONG uCheckSum; /* Check sum */
45c2c66affSColin Finck     ULONG uOffset; /* Offset from beginning of file */
46c2c66affSColin Finck     ULONG uLength; /* length of the table in bytes */
47*f4be6dc3SMikhail };
48c2c66affSColin Finck 
49*f4be6dc3SMikhail struct name_table_header
50*f4be6dc3SMikhail {
51c2c66affSColin Finck     USHORT uFSelector; /* format selector. Always 0 */
52c2c66affSColin Finck     USHORT uNRCount; /* Name Records count */
53*f4be6dc3SMikhail     USHORT uStorageOffset; /* Offset for strings storage from start of the table */
54*f4be6dc3SMikhail };
55c2c66affSColin Finck 
56c2c66affSColin Finck #define NAME_ID_FULL_FONT_NAME  4
57c2c66affSColin Finck #define NAME_ID_VERSION         5
58c2c66affSColin Finck 
59*f4be6dc3SMikhail struct name_record
60*f4be6dc3SMikhail {
61c2c66affSColin Finck     USHORT uPlatformID;
62c2c66affSColin Finck     USHORT uEncodingID;
63c2c66affSColin Finck     USHORT uLanguageID;
64c2c66affSColin Finck     USHORT uNameID;
65c2c66affSColin Finck     USHORT uStringLength;
66c2c66affSColin Finck     USHORT uStringOffset; /* from start of storage area */
67*f4be6dc3SMikhail };
68c2c66affSColin Finck 
69c2c66affSColin Finck #define SWAPWORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
70c2c66affSColin Finck #define SWAPLONG(x) MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x)))
71c2c66affSColin Finck 
72c2c66affSColin Finck /*
73c2c66affSColin Finck  * Code based off of code located here
74c2c66affSColin Finck  * http://www.codeproject.com/gdi/fontnamefromfile.asp
75c2c66affSColin Finck  */
load_ttf_name_id(MSIPACKAGE * package,const WCHAR * filename,DWORD id)76e342f337Swinesync static WCHAR *load_ttf_name_id( MSIPACKAGE *package, const WCHAR *filename, DWORD id )
77c2c66affSColin Finck {
78*f4be6dc3SMikhail     struct table_directory tblDir;
79c2c66affSColin Finck     BOOL bFound = FALSE;
80*f4be6dc3SMikhail     struct offset_table ttOffsetTable;
81*f4be6dc3SMikhail     struct name_table_header ttNTHeader;
82*f4be6dc3SMikhail     struct name_record ttRecord;
83c2c66affSColin Finck     DWORD dwRead;
84c2c66affSColin Finck     HANDLE handle;
85c2c66affSColin Finck     LPWSTR ret = NULL;
86c2c66affSColin Finck     int i;
87c2c66affSColin Finck 
88e342f337Swinesync     if (package)
89e342f337Swinesync         handle = msi_create_file( package, filename, GENERIC_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL );
90e342f337Swinesync     else
91e342f337Swinesync         handle = CreateFileW( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
92c2c66affSColin Finck     if (handle == INVALID_HANDLE_VALUE)
93c2c66affSColin Finck     {
94c2c66affSColin Finck         ERR("Unable to open font file %s\n", debugstr_w(filename));
95c2c66affSColin Finck         return NULL;
96c2c66affSColin Finck     }
97c2c66affSColin Finck 
98*f4be6dc3SMikhail     if (!ReadFile(handle,&ttOffsetTable, sizeof(struct offset_table),&dwRead,NULL))
99c2c66affSColin Finck         goto end;
100c2c66affSColin Finck 
101c2c66affSColin Finck     ttOffsetTable.uNumOfTables = SWAPWORD(ttOffsetTable.uNumOfTables);
102c2c66affSColin Finck     ttOffsetTable.uMajorVersion = SWAPWORD(ttOffsetTable.uMajorVersion);
103c2c66affSColin Finck     ttOffsetTable.uMinorVersion = SWAPWORD(ttOffsetTable.uMinorVersion);
104c2c66affSColin Finck 
105c2c66affSColin Finck     if ((ttOffsetTable.uMajorVersion != 1 || ttOffsetTable.uMinorVersion != 0) &&
106c2c66affSColin Finck         (ttOffsetTable.uMajorVersion != 0x4f54 || ttOffsetTable.uMinorVersion != 0x544f))
107c2c66affSColin Finck         goto end;
108c2c66affSColin Finck 
109c2c66affSColin Finck     for (i=0; i< ttOffsetTable.uNumOfTables; i++)
110c2c66affSColin Finck     {
111*f4be6dc3SMikhail         if (!ReadFile(handle, &tblDir, sizeof(tblDir), &dwRead, NULL))
112c2c66affSColin Finck             break;
113c2c66affSColin Finck         if (memcmp(tblDir.szTag,"name",4)==0)
114c2c66affSColin Finck         {
115c2c66affSColin Finck             bFound = TRUE;
116c2c66affSColin Finck             tblDir.uLength = SWAPLONG(tblDir.uLength);
117c2c66affSColin Finck             tblDir.uOffset = SWAPLONG(tblDir.uOffset);
118c2c66affSColin Finck             break;
119c2c66affSColin Finck         }
120c2c66affSColin Finck     }
121c2c66affSColin Finck 
122c2c66affSColin Finck     if (!bFound)
123c2c66affSColin Finck         goto end;
124c2c66affSColin Finck 
125c2c66affSColin Finck     SetFilePointer(handle, tblDir.uOffset, NULL, FILE_BEGIN);
126*f4be6dc3SMikhail     if (!ReadFile(handle, &ttNTHeader, sizeof(ttNTHeader), &dwRead, NULL))
127c2c66affSColin Finck         goto end;
128c2c66affSColin Finck 
129c2c66affSColin Finck     ttNTHeader.uNRCount = SWAPWORD(ttNTHeader.uNRCount);
130c2c66affSColin Finck     ttNTHeader.uStorageOffset = SWAPWORD(ttNTHeader.uStorageOffset);
131c2c66affSColin Finck     for(i=0; i<ttNTHeader.uNRCount; i++)
132c2c66affSColin Finck     {
133*f4be6dc3SMikhail         if (!ReadFile(handle, &ttRecord, sizeof(ttRecord), &dwRead, NULL))
134c2c66affSColin Finck             break;
135c2c66affSColin Finck 
136c2c66affSColin Finck         ttRecord.uNameID = SWAPWORD(ttRecord.uNameID);
137c2c66affSColin Finck         ttRecord.uPlatformID = SWAPWORD(ttRecord.uPlatformID);
138c2c66affSColin Finck         ttRecord.uEncodingID = SWAPWORD(ttRecord.uEncodingID);
139c2c66affSColin Finck         if (ttRecord.uNameID == id && ttRecord.uPlatformID == 3 &&
140c2c66affSColin Finck             (ttRecord.uEncodingID == 0 || ttRecord.uEncodingID == 1))
141c2c66affSColin Finck         {
142c2c66affSColin Finck             WCHAR *buf;
143c2c66affSColin Finck             unsigned int i;
144c2c66affSColin Finck 
145c2c66affSColin Finck             ttRecord.uStringLength = SWAPWORD(ttRecord.uStringLength);
146c2c66affSColin Finck             ttRecord.uStringOffset = SWAPWORD(ttRecord.uStringOffset);
147c2c66affSColin Finck             SetFilePointer(handle, tblDir.uOffset + ttRecord.uStringOffset + ttNTHeader.uStorageOffset,
148c2c66affSColin Finck                            NULL, FILE_BEGIN);
149*f4be6dc3SMikhail             if (!(buf = calloc(ttRecord.uStringLength, sizeof(WCHAR)))) goto end;
150c2c66affSColin Finck             dwRead = 0;
151c2c66affSColin Finck             ReadFile(handle, buf, ttRecord.uStringLength, &dwRead, NULL);
152c2c66affSColin Finck             if (dwRead % sizeof(WCHAR))
153c2c66affSColin Finck             {
154*f4be6dc3SMikhail                 free(buf);
155c2c66affSColin Finck                 goto end;
156c2c66affSColin Finck             }
157c2c66affSColin Finck             for (i = 0; i < dwRead / sizeof(WCHAR); i++) buf[i] = SWAPWORD(buf[i]);
158*f4be6dc3SMikhail             ret = wcsdup(buf);
159*f4be6dc3SMikhail             free(buf);
160c2c66affSColin Finck             break;
161c2c66affSColin Finck         }
162c2c66affSColin Finck     }
163c2c66affSColin Finck 
164c2c66affSColin Finck end:
165c2c66affSColin Finck     CloseHandle(handle);
166c2c66affSColin Finck     return ret;
167c2c66affSColin Finck }
168c2c66affSColin Finck 
font_name_from_file(MSIPACKAGE * package,const WCHAR * filename)169e342f337Swinesync static WCHAR *font_name_from_file( MSIPACKAGE *package, const WCHAR *filename )
170c2c66affSColin Finck {
171c2c66affSColin Finck     WCHAR *name, *ret = NULL;
172c2c66affSColin Finck 
173e342f337Swinesync     if ((name = load_ttf_name_id( package, filename, NAME_ID_FULL_FONT_NAME )))
174c2c66affSColin Finck     {
175c2c66affSColin Finck         if (!name[0])
176c2c66affSColin Finck         {
177c2c66affSColin Finck             WARN("empty font name\n");
178*f4be6dc3SMikhail             free( name );
179c2c66affSColin Finck             return NULL;
180c2c66affSColin Finck         }
181*f4be6dc3SMikhail         ret = malloc( wcslen( name ) * sizeof(WCHAR) + sizeof( L" (TrueType)" ) );
182958f1addSwinesync         lstrcpyW( ret, name );
18374f53b4bSwinesync         lstrcatW( ret, L" (TrueType)" );
184*f4be6dc3SMikhail         free( name );
185c2c66affSColin Finck     }
186c2c66affSColin Finck     return ret;
187c2c66affSColin Finck }
188c2c66affSColin Finck 
msi_get_font_file_version(MSIPACKAGE * package,const WCHAR * filename)189e342f337Swinesync WCHAR *msi_get_font_file_version( MSIPACKAGE *package, const WCHAR *filename )
190c2c66affSColin Finck {
191c2c66affSColin Finck     WCHAR *version, *p, *q, *ret = NULL;
192c2c66affSColin Finck 
193e342f337Swinesync     if ((version = load_ttf_name_id( package, filename, NAME_ID_VERSION )))
194c2c66affSColin Finck     {
195c2c66affSColin Finck         int len, major = 0, minor = 0;
196958f1addSwinesync         if ((p = wcschr( version, ';' ))) *p = 0;
197c2c66affSColin Finck         p = version;
198958f1addSwinesync         while (*p && !iswdigit( *p )) p++;
199958f1addSwinesync         if ((q = wcschr( p, '.' )))
200c2c66affSColin Finck         {
201958f1addSwinesync             major = wcstol( p, NULL, 10 );
202c2c66affSColin Finck             p = ++q;
203958f1addSwinesync             while (*q && iswdigit( *q )) q++;
204958f1addSwinesync             if (!*q || *q == ' ') minor = wcstol( p, NULL, 10 );
205c2c66affSColin Finck             else major = 0;
206c2c66affSColin Finck         }
20774f53b4bSwinesync         len = lstrlenW( L"%u.%u.0.0" ) + 20;
208*f4be6dc3SMikhail         ret = malloc( len * sizeof(WCHAR) );
20974f53b4bSwinesync         swprintf( ret, len, L"%u.%u.0.0", major, minor );
210*f4be6dc3SMikhail         free( version );
211c2c66affSColin Finck     }
212c2c66affSColin Finck     return ret;
213c2c66affSColin Finck }
214c2c66affSColin Finck 
ITERATE_RegisterFonts(MSIRECORD * row,LPVOID param)215c2c66affSColin Finck static UINT ITERATE_RegisterFonts(MSIRECORD *row, LPVOID param)
216c2c66affSColin Finck {
217c2c66affSColin Finck     MSIPACKAGE *package = param;
218c2c66affSColin Finck     LPWSTR name;
219c2c66affSColin Finck     LPCWSTR filename;
220c2c66affSColin Finck     MSIFILE *file;
221c2c66affSColin Finck     MSICOMPONENT *comp;
222c2c66affSColin Finck     HKEY hkey1, hkey2;
223c2c66affSColin Finck     MSIRECORD *uirow;
224c2c66affSColin Finck     LPWSTR uipath, p;
225c2c66affSColin Finck 
226c2c66affSColin Finck     filename = MSI_RecordGetString( row, 1 );
227c2c66affSColin Finck     file = msi_get_loaded_file( package, filename );
228c2c66affSColin Finck     if (!file)
229c2c66affSColin Finck     {
230c2c66affSColin Finck         WARN("unable to find file %s\n", debugstr_w(filename));
231c2c66affSColin Finck         return ERROR_SUCCESS;
232c2c66affSColin Finck     }
233c2c66affSColin Finck     comp = msi_get_loaded_component( package, file->Component->Component );
234c2c66affSColin Finck     if (!comp)
235c2c66affSColin Finck     {
236c2c66affSColin Finck         WARN("unable to find component %s\n", debugstr_w(file->Component->Component));
237c2c66affSColin Finck         return ERROR_SUCCESS;
238c2c66affSColin Finck     }
239c2c66affSColin Finck     comp->Action = msi_get_component_action( package, comp );
240c2c66affSColin Finck     if (comp->Action != INSTALLSTATE_LOCAL)
241c2c66affSColin Finck     {
242c2c66affSColin Finck         TRACE("component not scheduled for installation %s\n", debugstr_w(comp->Component));
243c2c66affSColin Finck         return ERROR_SUCCESS;
244c2c66affSColin Finck     }
245c2c66affSColin Finck 
24674f53b4bSwinesync     RegCreateKeyW( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts" ,&hkey1 );
24774f53b4bSwinesync     RegCreateKeyW( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Fonts", &hkey2 );
248c2c66affSColin Finck 
249c2c66affSColin Finck     if (MSI_RecordIsNull(row,2))
250e342f337Swinesync         name = font_name_from_file( package, file->TargetPath );
251c2c66affSColin Finck     else
252c2c66affSColin Finck         name = msi_dup_record_field(row,2);
253c2c66affSColin Finck 
254c2c66affSColin Finck     if (name)
255c2c66affSColin Finck     {
256c2c66affSColin Finck         msi_reg_set_val_str( hkey1, name, file->TargetPath);
257c2c66affSColin Finck         msi_reg_set_val_str( hkey2, name, file->TargetPath);
258c2c66affSColin Finck     }
259c2c66affSColin Finck 
260*f4be6dc3SMikhail     free(name);
261c2c66affSColin Finck     RegCloseKey(hkey1);
262c2c66affSColin Finck     RegCloseKey(hkey2);
263c2c66affSColin Finck 
264c2c66affSColin Finck     /* the UI chunk */
265c2c66affSColin Finck     uirow = MSI_CreateRecord( 1 );
266*f4be6dc3SMikhail     uipath = wcsdup( file->TargetPath );
267958f1addSwinesync     p = wcsrchr(uipath,'\\');
268c2c66affSColin Finck     if (p) p++;
269c2c66affSColin Finck     else p = uipath;
270c2c66affSColin Finck     MSI_RecordSetStringW( uirow, 1, p );
27171bffdcdSAmine Khaldi     MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONDATA, uirow);
272c2c66affSColin Finck     msiobj_release( &uirow->hdr );
273*f4be6dc3SMikhail     free( uipath );
274c2c66affSColin Finck     /* FIXME: call msi_ui_progress? */
275c2c66affSColin Finck 
276c2c66affSColin Finck     return ERROR_SUCCESS;
277c2c66affSColin Finck }
278c2c66affSColin Finck 
ACTION_RegisterFonts(MSIPACKAGE * package)279c2c66affSColin Finck UINT ACTION_RegisterFonts(MSIPACKAGE *package)
280c2c66affSColin Finck {
281c2c66affSColin Finck     MSIQUERY *view;
282c2c66affSColin Finck     UINT rc;
283c2c66affSColin Finck 
284fd8b07bdSwinesync     if (package->script == SCRIPT_NONE)
28574f53b4bSwinesync         return msi_schedule_action(package, SCRIPT_INSTALL, L"RegisterFonts");
286fd8b07bdSwinesync 
28774f53b4bSwinesync     rc = MSI_DatabaseOpenViewW(package->db, L"SELECT * FROM `Font`", &view);
288c2c66affSColin Finck     if (rc != ERROR_SUCCESS)
289c2c66affSColin Finck         return ERROR_SUCCESS;
290c2c66affSColin Finck 
291c2c66affSColin Finck     rc = MSI_IterateRecords(view, NULL, ITERATE_RegisterFonts, package);
292c2c66affSColin Finck     msiobj_release(&view->hdr);
293c2c66affSColin Finck     return rc;
294c2c66affSColin Finck }
295c2c66affSColin Finck 
ITERATE_UnregisterFonts(MSIRECORD * row,LPVOID param)296c2c66affSColin Finck static UINT ITERATE_UnregisterFonts( MSIRECORD *row, LPVOID param )
297c2c66affSColin Finck {
298c2c66affSColin Finck     MSIPACKAGE *package = param;
299c2c66affSColin Finck     LPWSTR name;
300c2c66affSColin Finck     LPCWSTR filename;
301c2c66affSColin Finck     MSIFILE *file;
302c2c66affSColin Finck     MSICOMPONENT *comp;
303c2c66affSColin Finck     HKEY hkey1, hkey2;
304c2c66affSColin Finck     MSIRECORD *uirow;
305c2c66affSColin Finck     LPWSTR uipath, p;
306c2c66affSColin Finck 
307c2c66affSColin Finck     filename = MSI_RecordGetString( row, 1 );
308c2c66affSColin Finck     file = msi_get_loaded_file( package, filename );
309c2c66affSColin Finck     if (!file)
310c2c66affSColin Finck     {
311c2c66affSColin Finck         WARN("unable to find file %s\n", debugstr_w(filename));
312c2c66affSColin Finck         return ERROR_SUCCESS;
313c2c66affSColin Finck     }
314c2c66affSColin Finck     comp = msi_get_loaded_component( package, file->Component->Component );
315c2c66affSColin Finck     if (!comp)
316c2c66affSColin Finck     {
317c2c66affSColin Finck         WARN("unable to find component %s\n", debugstr_w(file->Component->Component));
318c2c66affSColin Finck         return ERROR_SUCCESS;
319c2c66affSColin Finck     }
320c2c66affSColin Finck     comp->Action = msi_get_component_action( package, comp );
321c2c66affSColin Finck     if (comp->Action != INSTALLSTATE_ABSENT)
322c2c66affSColin Finck     {
323c2c66affSColin Finck         TRACE("component not scheduled for removal %s\n", debugstr_w(comp->Component));
324c2c66affSColin Finck         return ERROR_SUCCESS;
325c2c66affSColin Finck     }
326c2c66affSColin Finck 
32774f53b4bSwinesync     RegCreateKeyW( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts", &hkey1 );
32874f53b4bSwinesync     RegCreateKeyW( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Fonts", &hkey2 );
329c2c66affSColin Finck 
330c2c66affSColin Finck     if (MSI_RecordIsNull( row, 2 ))
331e342f337Swinesync         name = font_name_from_file( package, file->TargetPath );
332c2c66affSColin Finck     else
333c2c66affSColin Finck         name = msi_dup_record_field( row, 2 );
334c2c66affSColin Finck 
335c2c66affSColin Finck     if (name)
336c2c66affSColin Finck     {
337c2c66affSColin Finck         RegDeleteValueW( hkey1, name );
338c2c66affSColin Finck         RegDeleteValueW( hkey2, name );
339c2c66affSColin Finck     }
340c2c66affSColin Finck 
341*f4be6dc3SMikhail     free( name );
342c2c66affSColin Finck     RegCloseKey( hkey1 );
343c2c66affSColin Finck     RegCloseKey( hkey2 );
344c2c66affSColin Finck 
345c2c66affSColin Finck     /* the UI chunk */
346c2c66affSColin Finck     uirow = MSI_CreateRecord( 1 );
347*f4be6dc3SMikhail     uipath = wcsdup( file->TargetPath );
348958f1addSwinesync     p = wcsrchr( uipath,'\\' );
349c2c66affSColin Finck     if (p) p++;
350c2c66affSColin Finck     else p = uipath;
351c2c66affSColin Finck     MSI_RecordSetStringW( uirow, 1, p );
35271bffdcdSAmine Khaldi     MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONDATA, uirow);
353c2c66affSColin Finck     msiobj_release( &uirow->hdr );
354*f4be6dc3SMikhail     free( uipath );
355c2c66affSColin Finck     /* FIXME: call msi_ui_progress? */
356c2c66affSColin Finck 
357c2c66affSColin Finck     return ERROR_SUCCESS;
358c2c66affSColin Finck }
359c2c66affSColin Finck 
ACTION_UnregisterFonts(MSIPACKAGE * package)360c2c66affSColin Finck UINT ACTION_UnregisterFonts( MSIPACKAGE *package )
361c2c66affSColin Finck {
362c2c66affSColin Finck     MSIQUERY *view;
363c2c66affSColin Finck     UINT r;
364c2c66affSColin Finck 
365fd8b07bdSwinesync     if (package->script == SCRIPT_NONE)
36674f53b4bSwinesync         return msi_schedule_action(package, SCRIPT_INSTALL, L"UnregisterFonts");
367fd8b07bdSwinesync 
36874f53b4bSwinesync     r = MSI_DatabaseOpenViewW( package->db, L"SELECT * FROM `Font`", &view );
369c2c66affSColin Finck     if (r != ERROR_SUCCESS)
370c2c66affSColin Finck         return ERROR_SUCCESS;
371c2c66affSColin Finck 
372c2c66affSColin Finck     r = MSI_IterateRecords( view, NULL, ITERATE_UnregisterFonts, package );
373c2c66affSColin Finck     msiobj_release( &view->hdr );
374c2c66affSColin Finck     return r;
375c2c66affSColin Finck }
376