2 * Implementation of the Microsoft Installer (msi.dll)
4 * Copyright 2002,2003,2004,2005 Mike McCormack for CodeWeavers
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #define NONAMELESSUNION
30 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(msi);
42 * The MSVC headers define the MSIDBOPEN_* macros cast to LPCTSTR,
43 * which is a problem because LPCTSTR isn't defined when compiling wine.
44 * To work around this problem, we need to define LPCTSTR as LPCWSTR here,
45 * and make sure to only use it in W functions.
47 #define LPCTSTR LPCWSTR
49 DEFINE_GUID( CLSID_MsiDatabase, 0x000c1084, 0x0000, 0x0000,
50 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
51 DEFINE_GUID( CLSID_MsiPatch, 0x000c1086, 0x0000, 0x0000,
52 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
57 * An .msi file is a structured storage file.
58 * It contains a number of streams.
59 * A stream for each table in the database.
60 * Two streams for the string table in the database.
61 * Any binary data in a table is a reference to a stream.
64 static VOID MSI_CloseDatabase( MSIOBJECTHDR *arg )
66 MSIDATABASE *db = (MSIDATABASE *) arg;
69 free_cached_tables( db );
70 msi_destroy_stringtable( db->strings );
71 r = IStorage_Release( db->storage );
73 ERR("database reference count was not zero (%ld)\n", r);
76 UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb)
80 MSIDATABASE *db = NULL;
81 UINT ret = ERROR_FUNCTION_FAILED;
85 TRACE("%s %s\n",debugstr_w(szDBPath),debugstr_w(szPersist) );
88 return ERROR_INVALID_PARAMETER;
91 if( HIWORD( szPersist ) )
93 /* UINT len = lstrlenW( szPerist ) + 1; */
94 FIXME("don't support persist files yet\b");
95 return ERROR_INVALID_PARAMETER;
96 /* szMode = HeapAlloc( GetProcessHeap(), 0, len * sizeof (DWORD) ); */
98 else if( szPersist == MSIDBOPEN_READONLY )
100 r = StgOpenStorage( szDBPath, NULL,
101 STGM_DIRECT|STGM_READ|STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
103 else if( szPersist == MSIDBOPEN_CREATE )
105 r = StgCreateDocfile( szDBPath,
106 STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, 0, &stg);
107 if( r == ERROR_SUCCESS )
109 IStorage_SetClass( stg, &CLSID_MsiDatabase );
110 r = init_string_table( stg );
113 else if( szPersist == MSIDBOPEN_TRANSACT )
115 r = StgOpenStorage( szDBPath, NULL,
116 STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
120 ERR("unknown flag %p\n",szPersist);
121 return ERROR_INVALID_PARAMETER;
126 FIXME("open failed r = %08lx!\n",r);
127 return ERROR_FUNCTION_FAILED;
130 r = IStorage_Stat( stg, &stat, STATFLAG_NONAME );
133 FIXME("Failed to stat storage\n");
137 if(( memcmp( &stat.clsid, &CLSID_MsiDatabase, sizeof (GUID) ) )
138 && ( memcmp( &stat.clsid, &CLSID_MsiPatch, sizeof (GUID) ) ))
140 ERR("storage GUID is not a MSI database GUID %s\n",
141 debugstr_guid(&stat.clsid) );
146 db = alloc_msiobject( MSIHANDLETYPE_DATABASE, sizeof (MSIDATABASE),
150 FIXME("Failed to allocate a handle\n");
154 if( TRACE_ON( msi ) )
155 enum_stream_names( stg );
160 ret = load_string_table( db );
161 if( ret != ERROR_SUCCESS )
164 msiobj_addref( &db->hdr );
165 IStorage_AddRef( stg );
170 msiobj_release( &db->hdr );
172 IStorage_Release( stg );
177 UINT WINAPI MsiOpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIHANDLE *phDB)
182 TRACE("%s %s %p\n",debugstr_w(szDBPath),debugstr_w(szPersist), phDB);
184 ret = MSI_OpenDatabaseW( szDBPath, szPersist, &db );
185 if( ret == ERROR_SUCCESS )
187 *phDB = alloc_msihandle( &db->hdr );
188 msiobj_release( &db->hdr );
194 UINT WINAPI MsiOpenDatabaseA(LPCSTR szDBPath, LPCSTR szPersist, MSIHANDLE *phDB)
196 HRESULT r = ERROR_FUNCTION_FAILED;
197 LPWSTR szwDBPath = NULL, szwPersist = NULL;
199 TRACE("%s %s %p\n", debugstr_a(szDBPath), debugstr_a(szPersist), phDB);
203 szwDBPath = strdupAtoW( szDBPath );
208 if( HIWORD(szPersist) )
210 szwPersist = strdupAtoW( szPersist );
215 szwPersist = (LPWSTR)(DWORD)szPersist;
217 r = MsiOpenDatabaseW( szwDBPath, szwPersist, phDB );
220 if( HIWORD(szPersist) )
221 HeapFree( GetProcessHeap(), 0, szwPersist );
222 HeapFree( GetProcessHeap(), 0, szwDBPath );
227 UINT MSI_DatabaseImport( MSIDATABASE *db, LPCWSTR folder, LPCWSTR file )
229 FIXME("%p %s %s\n", db, debugstr_w(folder), debugstr_w(file) );
231 if( folder == NULL || file == NULL )
232 return ERROR_INVALID_PARAMETER;
234 return ERROR_CALL_NOT_IMPLEMENTED;
237 UINT WINAPI MsiDatabaseImportW(MSIHANDLE handle, LPCWSTR szFolder, LPCWSTR szFilename)
242 TRACE("%lx %s %s\n",handle,debugstr_w(szFolder), debugstr_w(szFilename));
244 db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE );
246 return ERROR_INVALID_HANDLE;
247 r = MSI_DatabaseImport( db, szFolder, szFilename );
248 msiobj_release( &db->hdr );
252 UINT WINAPI MsiDatabaseImportA( MSIHANDLE handle,
253 LPCSTR szFolder, LPCSTR szFilename )
255 LPWSTR path = NULL, file = NULL;
256 UINT r = ERROR_OUTOFMEMORY;
258 TRACE("%lx %s %s\n", handle, debugstr_a(szFolder), debugstr_a(szFilename));
262 path = strdupAtoW( szFolder );
269 file = strdupAtoW( szFilename );
274 r = MsiDatabaseImportW( handle, path, file );
277 HeapFree( GetProcessHeap(), 0, path );
278 HeapFree( GetProcessHeap(), 0, file );
283 UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
284 LPCWSTR folder, LPCWSTR file )
286 FIXME("%p %s %s %s\n", db, debugstr_w(table),
287 debugstr_w(folder), debugstr_w(file) );
289 if( folder == NULL || file == NULL )
290 return ERROR_INVALID_PARAMETER;
292 return ERROR_CALL_NOT_IMPLEMENTED;
295 UINT WINAPI MsiDatabaseExportW( MSIHANDLE handle, LPCWSTR szTable,
296 LPCWSTR szFolder, LPCWSTR szFilename )
301 TRACE("%lx %s %s %s\n", handle, debugstr_w(szTable),
302 debugstr_w(szFolder), debugstr_w(szFilename));
304 db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE );
306 return ERROR_INVALID_HANDLE;
307 r = MSI_DatabaseExport( db, szTable, szFolder, szFilename );
308 msiobj_release( &db->hdr );
312 UINT WINAPI MsiDatabaseExportA( MSIHANDLE handle, LPCSTR szTable,
313 LPCSTR szFolder, LPCSTR szFilename )
315 LPWSTR path = NULL, file = NULL, table = NULL;
316 UINT r = ERROR_OUTOFMEMORY;
318 TRACE("%lx %s %s %s\n", handle, debugstr_a(szTable),
319 debugstr_a(szFolder), debugstr_a(szFilename));
323 table = strdupAtoW( szTable );
330 path = strdupAtoW( szFolder );
337 file = strdupAtoW( szFilename );
342 r = MsiDatabaseExportW( handle, table, path, file );
345 HeapFree( GetProcessHeap(), 0, table );
346 HeapFree( GetProcessHeap(), 0, path );
347 HeapFree( GetProcessHeap(), 0, file );