Avoid referencing stackframe.h from outside kernel32.
[wine/testsucceed.git] / dlls / msi / database.c
blob800b1db2f57e115492767752ea75545ca64194a3
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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);
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);
53 * .MSI file format
55 * An .msi file is a structured storage file.
56 * It contains a number of streams.
57 * A stream for each table in the database.
58 * Two streams for the string table in the database.
59 * Any binary data in a table is a reference to a stream.
62 VOID MSI_CloseDatabase( MSIOBJECTHDR *arg )
64 MSIDATABASE *db = (MSIDATABASE *) arg;
65 DWORD r;
67 free_cached_tables( db );
68 msi_destroy_stringtable( db->strings );
69 r = IStorage_Release( db->storage );
70 if( r )
71 ERR("database reference count was not zero (%ld)\n", r);
74 UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb)
76 IStorage *stg = NULL;
77 HRESULT r;
78 MSIDATABASE *db = NULL;
79 UINT ret = ERROR_FUNCTION_FAILED;
80 LPWSTR szMode;
81 STATSTG stat;
83 TRACE("%s %s\n",debugstr_w(szDBPath),debugstr_w(szPersist) );
85 if( !pdb )
86 return ERROR_INVALID_PARAMETER;
88 szMode = (LPWSTR) szPersist;
89 if( HIWORD( szPersist ) )
91 /* UINT len = lstrlenW( szPerist ) + 1; */
92 FIXME("don't support persist files yet\b");
93 return ERROR_INVALID_PARAMETER;
94 /* szMode = HeapAlloc( GetProcessHeap(), 0, len * sizeof (DWORD) ); */
96 else if( szPersist == MSIDBOPEN_READONLY )
98 r = StgOpenStorage( szDBPath, NULL,
99 STGM_DIRECT|STGM_READ|STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
101 else if( szPersist == MSIDBOPEN_CREATE )
103 r = StgCreateDocfile( szDBPath,
104 STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, 0, &stg);
105 if( r == ERROR_SUCCESS )
107 IStorage_SetClass( stg, &CLSID_MsiDatabase );
108 r = init_string_table( stg );
111 else if( szPersist == MSIDBOPEN_TRANSACT )
113 r = StgOpenStorage( szDBPath, NULL,
114 STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
116 else
118 ERR("unknown flag %p\n",szPersist);
119 return ERROR_INVALID_PARAMETER;
122 if( FAILED( r ) )
124 FIXME("open failed r = %08lx!\n",r);
125 return ERROR_FUNCTION_FAILED;
128 r = IStorage_Stat( stg, &stat, STATFLAG_NONAME );
129 if( FAILED( r ) )
131 FIXME("Failed to stat storage\n");
132 goto end;
135 if( memcmp( &stat.clsid, &CLSID_MsiDatabase, sizeof (GUID) ) )
137 ERR("storage GUID is not a MSI database GUID %s\n",
138 debugstr_guid(&stat.clsid) );
139 goto end;
143 db = alloc_msiobject( MSIHANDLETYPE_DATABASE, sizeof (MSIDATABASE),
144 MSI_CloseDatabase );
145 if( !db )
147 FIXME("Failed to allocate a handle\n");
148 goto end;
151 if( TRACE_ON( msi ) )
152 enum_stream_names( stg );
154 db->storage = stg;
155 db->mode = szMode;
157 ret = load_string_table( db );
158 if( ret != ERROR_SUCCESS )
159 goto end;
161 msiobj_addref( &db->hdr );
162 IStorage_AddRef( stg );
163 *pdb = db;
165 end:
166 if( db )
167 msiobj_release( &db->hdr );
168 if( stg )
169 IStorage_Release( stg );
171 return ret;
174 UINT WINAPI MsiOpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIHANDLE *phDB)
176 MSIDATABASE *db;
177 UINT ret;
179 TRACE("%s %s %p\n",debugstr_w(szDBPath),debugstr_w(szPersist), phDB);
181 ret = MSI_OpenDatabaseW( szDBPath, szPersist, &db );
182 if( ret == ERROR_SUCCESS )
184 *phDB = alloc_msihandle( &db->hdr );
185 msiobj_release( &db->hdr );
188 return ret;
191 UINT WINAPI MsiOpenDatabaseA(LPCSTR szDBPath, LPCSTR szPersist, MSIHANDLE *phDB)
193 HRESULT r = ERROR_FUNCTION_FAILED;
194 LPWSTR szwDBPath = NULL, szwPersist = NULL;
196 TRACE("%s %s %p\n", debugstr_a(szDBPath), debugstr_a(szPersist), phDB);
198 if( szDBPath )
200 szwDBPath = strdupAtoW( szDBPath );
201 if( !szwDBPath )
202 goto end;
205 if( HIWORD(szPersist) )
207 szwPersist = strdupAtoW( szPersist );
208 if( !szwPersist )
209 goto end;
211 else
212 szwPersist = (LPWSTR) szPersist;
214 r = MsiOpenDatabaseW( szwDBPath, szwPersist, phDB );
216 end:
217 if( HIWORD(szPersist) )
218 HeapFree( GetProcessHeap(), 0, szwPersist );
219 HeapFree( GetProcessHeap(), 0, szwDBPath );
221 return r;
224 UINT MSI_DatabaseImport( MSIDATABASE *db, LPCWSTR folder, LPCWSTR file )
226 FIXME("%p %s %s\n", db, debugstr_w(folder), debugstr_w(file) );
228 if( folder == NULL || file == NULL )
229 return ERROR_INVALID_PARAMETER;
231 return ERROR_CALL_NOT_IMPLEMENTED;
234 UINT WINAPI MsiDatabaseImportW(MSIHANDLE handle, LPCWSTR szFolder, LPCWSTR szFilename)
236 MSIDATABASE *db;
237 UINT r;
239 TRACE("%lx %s %s\n",handle,debugstr_w(szFolder), debugstr_w(szFilename));
241 db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE );
242 if( !db )
243 return ERROR_INVALID_HANDLE;
244 r = MSI_DatabaseImport( db, szFolder, szFilename );
245 msiobj_release( &db->hdr );
246 return r;
249 UINT WINAPI MsiDatabaseImportA( MSIHANDLE handle,
250 LPCSTR szFolder, LPCSTR szFilename )
252 LPWSTR path = NULL, file = NULL;
253 UINT r = ERROR_OUTOFMEMORY;
255 TRACE("%lx %s %s\n", handle, debugstr_a(szFolder), debugstr_a(szFilename));
257 if( szFolder )
259 path = strdupAtoW( szFolder );
260 if( !path )
261 goto end;
264 if( szFilename )
266 file = strdupAtoW( szFilename );
267 if( !file )
268 goto end;
271 r = MsiDatabaseImportW( handle, path, file );
273 end:
274 HeapFree( GetProcessHeap(), 0, path );
275 HeapFree( GetProcessHeap(), 0, file );
277 return r;
280 UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
281 LPCWSTR folder, LPCWSTR file )
283 FIXME("%p %s %s %s\n", db, debugstr_w(table),
284 debugstr_w(folder), debugstr_w(file) );
286 if( folder == NULL || file == NULL )
287 return ERROR_INVALID_PARAMETER;
289 return ERROR_CALL_NOT_IMPLEMENTED;
292 UINT WINAPI MsiDatabaseExportW( MSIHANDLE handle, LPCWSTR szTable,
293 LPCWSTR szFolder, LPCWSTR szFilename )
295 MSIDATABASE *db;
296 UINT r;
298 TRACE("%lx %s %s %s\n", handle, debugstr_w(szTable),
299 debugstr_w(szFolder), debugstr_w(szFilename));
301 db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE );
302 if( !db )
303 return ERROR_INVALID_HANDLE;
304 r = MSI_DatabaseExport( db, szTable, szFolder, szFilename );
305 msiobj_release( &db->hdr );
306 return r;
309 UINT WINAPI MsiDatabaseExportA( MSIHANDLE handle, LPCSTR szTable,
310 LPCSTR szFolder, LPCSTR szFilename )
312 LPWSTR path = NULL, file = NULL, table = NULL;
313 UINT r = ERROR_OUTOFMEMORY;
315 TRACE("%lx %s %s %s\n", handle, debugstr_a(szTable),
316 debugstr_a(szFolder), debugstr_a(szFilename));
318 if( szTable )
320 table = strdupAtoW( szTable );
321 if( !table )
322 goto end;
325 if( szFolder )
327 path = strdupAtoW( szFolder );
328 if( !path )
329 goto end;
332 if( szFilename )
334 file = strdupAtoW( szFilename );
335 if( !file )
336 goto end;
339 r = MsiDatabaseExportW( handle, table, path, file );
341 end:
342 HeapFree( GetProcessHeap(), 0, table );
343 HeapFree( GetProcessHeap(), 0, path );
344 HeapFree( GetProcessHeap(), 0, file );
346 return r;