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
);
41 DEFINE_GUID( CLSID_MsiDatabase
, 0x000c1084, 0x0000, 0x0000,
42 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
43 DEFINE_GUID( CLSID_MsiPatch
, 0x000c1086, 0x0000, 0x0000,
44 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
49 * An .msi file is a structured storage file.
50 * It contains a number of streams.
51 * A stream for each table in the database.
52 * Two streams for the string table in the database.
53 * Any binary data in a table is a reference to a stream.
56 static VOID
MSI_CloseDatabase( MSIOBJECTHDR
*arg
)
58 MSIDATABASE
*db
= (MSIDATABASE
*) arg
;
61 free_cached_tables( db
);
62 msi_free_transforms( db
);
63 msi_destroy_stringtable( db
->strings
);
64 r
= IStorage_Release( db
->storage
);
66 ERR("database reference count was not zero (%ld)\n", r
);
69 UINT
MSI_OpenDatabaseW(LPCWSTR szDBPath
, LPCWSTR szPersist
, MSIDATABASE
**pdb
)
73 MSIDATABASE
*db
= NULL
;
74 UINT ret
= ERROR_FUNCTION_FAILED
;
78 TRACE("%s %s\n",debugstr_w(szDBPath
),debugstr_w(szPersist
) );
81 return ERROR_INVALID_PARAMETER
;
84 if( HIWORD( szPersist
) )
86 /* UINT len = lstrlenW( szPerist ) + 1; */
87 FIXME("don't support persist files yet\b");
88 return ERROR_INVALID_PARAMETER
;
89 /* szMode = msi_alloc( len * sizeof (DWORD) ); */
91 else if( szPersist
== MSIDBOPEN_READONLY
)
93 r
= StgOpenStorage( szDBPath
, NULL
,
94 STGM_DIRECT
|STGM_READ
|STGM_SHARE_DENY_WRITE
, NULL
, 0, &stg
);
96 else if( szPersist
== MSIDBOPEN_CREATE
)
98 r
= StgCreateDocfile( szDBPath
,
99 STGM_DIRECT
|STGM_READWRITE
|STGM_SHARE_EXCLUSIVE
, 0, &stg
);
100 if( r
== ERROR_SUCCESS
)
102 IStorage_SetClass( stg
, &CLSID_MsiDatabase
);
103 r
= init_string_table( stg
);
106 else if( szPersist
== MSIDBOPEN_TRANSACT
)
108 r
= StgOpenStorage( szDBPath
, NULL
,
109 STGM_DIRECT
|STGM_READWRITE
|STGM_SHARE_EXCLUSIVE
, NULL
, 0, &stg
);
113 ERR("unknown flag %p\n",szPersist
);
114 return ERROR_INVALID_PARAMETER
;
119 FIXME("open failed r = %08lx!\n",r
);
120 return ERROR_FUNCTION_FAILED
;
123 r
= IStorage_Stat( stg
, &stat
, STATFLAG_NONAME
);
126 FIXME("Failed to stat storage\n");
130 if ( !IsEqualGUID( &stat
.clsid
, &CLSID_MsiDatabase
) &&
131 !IsEqualGUID( &stat
.clsid
, &CLSID_MsiPatch
) )
133 ERR("storage GUID is not a MSI database GUID %s\n",
134 debugstr_guid(&stat
.clsid
) );
138 db
= alloc_msiobject( MSIHANDLETYPE_DATABASE
, sizeof (MSIDATABASE
),
142 FIXME("Failed to allocate a handle\n");
146 if( TRACE_ON( msi
) )
147 enum_stream_names( stg
);
151 list_init( &db
->tables
);
152 list_init( &db
->transforms
);
154 db
->strings
= load_string_table( stg
);
160 msiobj_addref( &db
->hdr
);
161 IStorage_AddRef( stg
);
166 msiobj_release( &db
->hdr
);
168 IStorage_Release( stg
);
173 UINT WINAPI
MsiOpenDatabaseW(LPCWSTR szDBPath
, LPCWSTR szPersist
, MSIHANDLE
*phDB
)
178 TRACE("%s %s %p\n",debugstr_w(szDBPath
),debugstr_w(szPersist
), phDB
);
180 ret
= MSI_OpenDatabaseW( szDBPath
, szPersist
, &db
);
181 if( ret
== ERROR_SUCCESS
)
183 *phDB
= alloc_msihandle( &db
->hdr
);
184 msiobj_release( &db
->hdr
);
190 UINT WINAPI
MsiOpenDatabaseA(LPCSTR szDBPath
, LPCSTR szPersist
, MSIHANDLE
*phDB
)
192 HRESULT r
= ERROR_FUNCTION_FAILED
;
193 LPWSTR szwDBPath
= NULL
, szwPersist
= NULL
;
195 TRACE("%s %s %p\n", debugstr_a(szDBPath
), debugstr_a(szPersist
), phDB
);
199 szwDBPath
= strdupAtoW( szDBPath
);
204 if( HIWORD(szPersist
) )
206 szwPersist
= strdupAtoW( szPersist
);
211 szwPersist
= (LPWSTR
)(DWORD
)szPersist
;
213 r
= MsiOpenDatabaseW( szwDBPath
, szwPersist
, phDB
);
216 if( HIWORD(szPersist
) )
217 msi_free( szwPersist
);
218 msi_free( szwDBPath
);
223 UINT
MSI_DatabaseImport( MSIDATABASE
*db
, LPCWSTR folder
, LPCWSTR file
)
225 FIXME("%p %s %s\n", db
, debugstr_w(folder
), debugstr_w(file
) );
227 if( folder
== NULL
|| file
== NULL
)
228 return ERROR_INVALID_PARAMETER
;
230 return ERROR_CALL_NOT_IMPLEMENTED
;
233 UINT WINAPI
MsiDatabaseImportW(MSIHANDLE handle
, LPCWSTR szFolder
, LPCWSTR szFilename
)
238 TRACE("%lx %s %s\n",handle
,debugstr_w(szFolder
), debugstr_w(szFilename
));
240 db
= msihandle2msiinfo( handle
, MSIHANDLETYPE_DATABASE
);
242 return ERROR_INVALID_HANDLE
;
243 r
= MSI_DatabaseImport( db
, szFolder
, szFilename
);
244 msiobj_release( &db
->hdr
);
248 UINT WINAPI
MsiDatabaseImportA( MSIHANDLE handle
,
249 LPCSTR szFolder
, LPCSTR szFilename
)
251 LPWSTR path
= NULL
, file
= NULL
;
252 UINT r
= ERROR_OUTOFMEMORY
;
254 TRACE("%lx %s %s\n", handle
, debugstr_a(szFolder
), debugstr_a(szFilename
));
258 path
= strdupAtoW( szFolder
);
265 file
= strdupAtoW( szFilename
);
270 r
= MsiDatabaseImportW( handle
, path
, file
);
279 UINT
MSI_DatabaseExport( MSIDATABASE
*db
, LPCWSTR table
,
280 LPCWSTR folder
, LPCWSTR file
)
282 FIXME("%p %s %s %s\n", db
, debugstr_w(table
),
283 debugstr_w(folder
), debugstr_w(file
) );
285 if( folder
== NULL
|| file
== NULL
)
286 return ERROR_INVALID_PARAMETER
;
288 return ERROR_CALL_NOT_IMPLEMENTED
;
291 UINT WINAPI
MsiDatabaseExportW( MSIHANDLE handle
, LPCWSTR szTable
,
292 LPCWSTR szFolder
, LPCWSTR szFilename
)
297 TRACE("%lx %s %s %s\n", handle
, debugstr_w(szTable
),
298 debugstr_w(szFolder
), debugstr_w(szFilename
));
300 db
= msihandle2msiinfo( handle
, MSIHANDLETYPE_DATABASE
);
302 return ERROR_INVALID_HANDLE
;
303 r
= MSI_DatabaseExport( db
, szTable
, szFolder
, szFilename
);
304 msiobj_release( &db
->hdr
);
308 UINT WINAPI
MsiDatabaseExportA( MSIHANDLE handle
, LPCSTR szTable
,
309 LPCSTR szFolder
, LPCSTR szFilename
)
311 LPWSTR path
= NULL
, file
= NULL
, table
= NULL
;
312 UINT r
= ERROR_OUTOFMEMORY
;
314 TRACE("%lx %s %s %s\n", handle
, debugstr_a(szTable
),
315 debugstr_a(szFolder
), debugstr_a(szFilename
));
319 table
= strdupAtoW( szTable
);
326 path
= strdupAtoW( szFolder
);
333 file
= strdupAtoW( szFilename
);
338 r
= MsiDatabaseExportW( handle
, table
, path
, file
);