wininet/tests: Write-strings warnings fix.
[wine/multimedia.git] / dlls / msi / database.c
blob0dc3f858d2901600fc7efb4648ce9f6b2f982bfd
1 /*
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
23 #define COBJMACROS
24 #define NONAMELESSUNION
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "winnls.h"
30 #include "wine/debug.h"
31 #include "msi.h"
32 #include "msiquery.h"
33 #include "msipriv.h"
34 #include "objidl.h"
35 #include "objbase.h"
37 #include "initguid.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);
47 * .MSI file format
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;
59 DWORD r;
61 free_cached_tables( db );
62 msi_free_transforms( db );
63 msi_destroy_stringtable( db->strings );
64 r = IStorage_Release( db->storage );
65 if( r )
66 ERR("database reference count was not zero (%ld)\n", r);
69 UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb)
71 IStorage *stg = NULL;
72 HRESULT r;
73 MSIDATABASE *db = NULL;
74 UINT ret = ERROR_FUNCTION_FAILED;
75 LPCWSTR szMode;
76 STATSTG stat;
78 TRACE("%s %s\n",debugstr_w(szDBPath),debugstr_w(szPersist) );
80 if( !pdb )
81 return ERROR_INVALID_PARAMETER;
83 szMode = szPersist;
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 || szPersist == MSIDBOPEN_CREATEDIRECT )
98 /* FIXME: MSIDBOPEN_CREATE should case STGM_TRANSACTED flag to be
99 * used here: */
100 r = StgCreateDocfile( szDBPath,
101 STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, 0, &stg);
102 if( r == ERROR_SUCCESS )
104 IStorage_SetClass( stg, &CLSID_MsiDatabase );
105 r = init_string_table( stg );
108 else if( szPersist == MSIDBOPEN_TRANSACT )
110 /* FIXME: MSIDBOPEN_TRANSACT should case STGM_TRANSACTED flag to be
111 * used here: */
112 r = StgOpenStorage( szDBPath, NULL,
113 STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
115 else if( szPersist == MSIDBOPEN_DIRECT )
117 r = StgOpenStorage( szDBPath, NULL,
118 STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
120 else
122 ERR("unknown flag %p\n",szPersist);
123 return ERROR_INVALID_PARAMETER;
126 if( FAILED( r ) )
128 FIXME("open failed r = %08lx!\n",r);
129 return ERROR_FUNCTION_FAILED;
132 r = IStorage_Stat( stg, &stat, STATFLAG_NONAME );
133 if( FAILED( r ) )
135 FIXME("Failed to stat storage\n");
136 goto end;
139 if ( !IsEqualGUID( &stat.clsid, &CLSID_MsiDatabase ) &&
140 !IsEqualGUID( &stat.clsid, &CLSID_MsiPatch ) )
142 ERR("storage GUID is not a MSI database GUID %s\n",
143 debugstr_guid(&stat.clsid) );
144 goto end;
147 db = alloc_msiobject( MSIHANDLETYPE_DATABASE, sizeof (MSIDATABASE),
148 MSI_CloseDatabase );
149 if( !db )
151 FIXME("Failed to allocate a handle\n");
152 goto end;
155 if( TRACE_ON( msi ) )
156 enum_stream_names( stg );
158 db->storage = stg;
159 db->mode = szMode;
160 list_init( &db->tables );
161 list_init( &db->transforms );
163 db->strings = load_string_table( stg );
164 if( !db->strings )
165 goto end;
167 ret = ERROR_SUCCESS;
169 msiobj_addref( &db->hdr );
170 IStorage_AddRef( stg );
171 *pdb = db;
173 end:
174 if( db )
175 msiobj_release( &db->hdr );
176 if( stg )
177 IStorage_Release( stg );
179 return ret;
182 UINT WINAPI MsiOpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIHANDLE *phDB)
184 MSIDATABASE *db;
185 UINT ret;
187 TRACE("%s %s %p\n",debugstr_w(szDBPath),debugstr_w(szPersist), phDB);
189 ret = MSI_OpenDatabaseW( szDBPath, szPersist, &db );
190 if( ret == ERROR_SUCCESS )
192 *phDB = alloc_msihandle( &db->hdr );
193 msiobj_release( &db->hdr );
196 return ret;
199 UINT WINAPI MsiOpenDatabaseA(LPCSTR szDBPath, LPCSTR szPersist, MSIHANDLE *phDB)
201 HRESULT r = ERROR_FUNCTION_FAILED;
202 LPWSTR szwDBPath = NULL, szwPersist = NULL;
204 TRACE("%s %s %p\n", debugstr_a(szDBPath), debugstr_a(szPersist), phDB);
206 if( szDBPath )
208 szwDBPath = strdupAtoW( szDBPath );
209 if( !szwDBPath )
210 goto end;
213 if( HIWORD(szPersist) )
215 szwPersist = strdupAtoW( szPersist );
216 if( !szwPersist )
217 goto end;
219 else
220 szwPersist = (LPWSTR)(DWORD_PTR)szPersist;
222 r = MsiOpenDatabaseW( szwDBPath, szwPersist, phDB );
224 end:
225 if( HIWORD(szPersist) )
226 msi_free( szwPersist );
227 msi_free( szwDBPath );
229 return r;
232 UINT MSI_DatabaseImport( MSIDATABASE *db, LPCWSTR folder, LPCWSTR file )
234 FIXME("%p %s %s\n", db, debugstr_w(folder), debugstr_w(file) );
236 if( folder == NULL || file == NULL )
237 return ERROR_INVALID_PARAMETER;
239 return ERROR_CALL_NOT_IMPLEMENTED;
242 UINT WINAPI MsiDatabaseImportW(MSIHANDLE handle, LPCWSTR szFolder, LPCWSTR szFilename)
244 MSIDATABASE *db;
245 UINT r;
247 TRACE("%lx %s %s\n",handle,debugstr_w(szFolder), debugstr_w(szFilename));
249 db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE );
250 if( !db )
251 return ERROR_INVALID_HANDLE;
252 r = MSI_DatabaseImport( db, szFolder, szFilename );
253 msiobj_release( &db->hdr );
254 return r;
257 UINT WINAPI MsiDatabaseImportA( MSIHANDLE handle,
258 LPCSTR szFolder, LPCSTR szFilename )
260 LPWSTR path = NULL, file = NULL;
261 UINT r = ERROR_OUTOFMEMORY;
263 TRACE("%lx %s %s\n", handle, debugstr_a(szFolder), debugstr_a(szFilename));
265 if( szFolder )
267 path = strdupAtoW( szFolder );
268 if( !path )
269 goto end;
272 if( szFilename )
274 file = strdupAtoW( szFilename );
275 if( !file )
276 goto end;
279 r = MsiDatabaseImportW( handle, path, file );
281 end:
282 msi_free( path );
283 msi_free( file );
285 return r;
288 UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
289 LPCWSTR folder, LPCWSTR file )
291 FIXME("%p %s %s %s\n", db, debugstr_w(table),
292 debugstr_w(folder), debugstr_w(file) );
294 if( folder == NULL || file == NULL )
295 return ERROR_INVALID_PARAMETER;
297 return ERROR_CALL_NOT_IMPLEMENTED;
300 UINT WINAPI MsiDatabaseExportW( MSIHANDLE handle, LPCWSTR szTable,
301 LPCWSTR szFolder, LPCWSTR szFilename )
303 MSIDATABASE *db;
304 UINT r;
306 TRACE("%lx %s %s %s\n", handle, debugstr_w(szTable),
307 debugstr_w(szFolder), debugstr_w(szFilename));
309 db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE );
310 if( !db )
311 return ERROR_INVALID_HANDLE;
312 r = MSI_DatabaseExport( db, szTable, szFolder, szFilename );
313 msiobj_release( &db->hdr );
314 return r;
317 UINT WINAPI MsiDatabaseExportA( MSIHANDLE handle, LPCSTR szTable,
318 LPCSTR szFolder, LPCSTR szFilename )
320 LPWSTR path = NULL, file = NULL, table = NULL;
321 UINT r = ERROR_OUTOFMEMORY;
323 TRACE("%lx %s %s %s\n", handle, debugstr_a(szTable),
324 debugstr_a(szFolder), debugstr_a(szFilename));
326 if( szTable )
328 table = strdupAtoW( szTable );
329 if( !table )
330 goto end;
333 if( szFolder )
335 path = strdupAtoW( szFolder );
336 if( !path )
337 goto end;
340 if( szFilename )
342 file = strdupAtoW( szFilename );
343 if( !file )
344 goto end;
347 r = MsiDatabaseExportW( handle, table, path, file );
349 end:
350 msi_free( table );
351 msi_free( path );
352 msi_free( file );
354 return r;
357 MSIDBSTATE WINAPI MsiGetDatabaseState( MSIHANDLE handle )
359 MSIDBSTATE ret = MSIDBSTATE_READ;
360 MSIDATABASE *db;
362 TRACE("%ld\n", handle);
364 db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE );
365 if (!db)
366 return MSIDBSTATE_ERROR;
367 if (db->mode != MSIDBOPEN_READONLY )
368 ret = MSIDBSTATE_WRITE;
369 msiobj_release( &db->hdr );
371 return ret;