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_free_transforms( db
);
71 msi_destroy_stringtable( db
->strings
);
72 r
= IStorage_Release( db
->storage
);
74 ERR("database reference count was not zero (%ld)\n", r
);
77 UINT
MSI_OpenDatabaseW(LPCWSTR szDBPath
, LPCWSTR szPersist
, MSIDATABASE
**pdb
)
81 MSIDATABASE
*db
= NULL
;
82 UINT ret
= ERROR_FUNCTION_FAILED
;
86 TRACE("%s %s\n",debugstr_w(szDBPath
),debugstr_w(szPersist
) );
89 return ERROR_INVALID_PARAMETER
;
92 if( HIWORD( szPersist
) )
94 /* UINT len = lstrlenW( szPerist ) + 1; */
95 FIXME("don't support persist files yet\b");
96 return ERROR_INVALID_PARAMETER
;
97 /* szMode = msi_alloc( len * sizeof (DWORD) ); */
99 else if( szPersist
== MSIDBOPEN_READONLY
)
101 r
= StgOpenStorage( szDBPath
, NULL
,
102 STGM_DIRECT
|STGM_READ
|STGM_SHARE_DENY_WRITE
, NULL
, 0, &stg
);
104 else if( szPersist
== MSIDBOPEN_CREATE
)
106 r
= StgCreateDocfile( szDBPath
,
107 STGM_DIRECT
|STGM_READWRITE
|STGM_SHARE_EXCLUSIVE
, 0, &stg
);
108 if( r
== ERROR_SUCCESS
)
110 IStorage_SetClass( stg
, &CLSID_MsiDatabase
);
111 r
= init_string_table( stg
);
114 else if( szPersist
== MSIDBOPEN_TRANSACT
)
116 r
= StgOpenStorage( szDBPath
, NULL
,
117 STGM_DIRECT
|STGM_READWRITE
|STGM_SHARE_EXCLUSIVE
, NULL
, 0, &stg
);
121 ERR("unknown flag %p\n",szPersist
);
122 return ERROR_INVALID_PARAMETER
;
127 FIXME("open failed r = %08lx!\n",r
);
128 return ERROR_FUNCTION_FAILED
;
131 r
= IStorage_Stat( stg
, &stat
, STATFLAG_NONAME
);
134 FIXME("Failed to stat storage\n");
138 if ( !IsEqualGUID( &stat
.clsid
, &CLSID_MsiDatabase
) &&
139 !IsEqualGUID( &stat
.clsid
, &CLSID_MsiPatch
) )
141 ERR("storage GUID is not a MSI database GUID %s\n",
142 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
);
159 list_init( &db
->tables
);
160 list_init( &db
->transforms
);
162 db
->strings
= load_string_table( stg
);
168 msiobj_addref( &db
->hdr
);
169 IStorage_AddRef( stg
);
174 msiobj_release( &db
->hdr
);
176 IStorage_Release( stg
);
181 UINT WINAPI
MsiOpenDatabaseW(LPCWSTR szDBPath
, LPCWSTR szPersist
, MSIHANDLE
*phDB
)
186 TRACE("%s %s %p\n",debugstr_w(szDBPath
),debugstr_w(szPersist
), phDB
);
188 ret
= MSI_OpenDatabaseW( szDBPath
, szPersist
, &db
);
189 if( ret
== ERROR_SUCCESS
)
191 *phDB
= alloc_msihandle( &db
->hdr
);
192 msiobj_release( &db
->hdr
);
198 UINT WINAPI
MsiOpenDatabaseA(LPCSTR szDBPath
, LPCSTR szPersist
, MSIHANDLE
*phDB
)
200 HRESULT r
= ERROR_FUNCTION_FAILED
;
201 LPWSTR szwDBPath
= NULL
, szwPersist
= NULL
;
203 TRACE("%s %s %p\n", debugstr_a(szDBPath
), debugstr_a(szPersist
), phDB
);
207 szwDBPath
= strdupAtoW( szDBPath
);
212 if( HIWORD(szPersist
) )
214 szwPersist
= strdupAtoW( szPersist
);
219 szwPersist
= (LPWSTR
)(DWORD
)szPersist
;
221 r
= MsiOpenDatabaseW( szwDBPath
, szwPersist
, phDB
);
224 if( HIWORD(szPersist
) )
225 msi_free( szwPersist
);
226 msi_free( szwDBPath
);
231 UINT
MSI_DatabaseImport( MSIDATABASE
*db
, LPCWSTR folder
, LPCWSTR file
)
233 FIXME("%p %s %s\n", db
, debugstr_w(folder
), debugstr_w(file
) );
235 if( folder
== NULL
|| file
== NULL
)
236 return ERROR_INVALID_PARAMETER
;
238 return ERROR_CALL_NOT_IMPLEMENTED
;
241 UINT WINAPI
MsiDatabaseImportW(MSIHANDLE handle
, LPCWSTR szFolder
, LPCWSTR szFilename
)
246 TRACE("%lx %s %s\n",handle
,debugstr_w(szFolder
), debugstr_w(szFilename
));
248 db
= msihandle2msiinfo( handle
, MSIHANDLETYPE_DATABASE
);
250 return ERROR_INVALID_HANDLE
;
251 r
= MSI_DatabaseImport( db
, szFolder
, szFilename
);
252 msiobj_release( &db
->hdr
);
256 UINT WINAPI
MsiDatabaseImportA( MSIHANDLE handle
,
257 LPCSTR szFolder
, LPCSTR szFilename
)
259 LPWSTR path
= NULL
, file
= NULL
;
260 UINT r
= ERROR_OUTOFMEMORY
;
262 TRACE("%lx %s %s\n", handle
, debugstr_a(szFolder
), debugstr_a(szFilename
));
266 path
= strdupAtoW( szFolder
);
273 file
= strdupAtoW( szFilename
);
278 r
= MsiDatabaseImportW( handle
, path
, file
);
287 UINT
MSI_DatabaseExport( MSIDATABASE
*db
, LPCWSTR table
,
288 LPCWSTR folder
, LPCWSTR file
)
290 FIXME("%p %s %s %s\n", db
, debugstr_w(table
),
291 debugstr_w(folder
), debugstr_w(file
) );
293 if( folder
== NULL
|| file
== NULL
)
294 return ERROR_INVALID_PARAMETER
;
296 return ERROR_CALL_NOT_IMPLEMENTED
;
299 UINT WINAPI
MsiDatabaseExportW( MSIHANDLE handle
, LPCWSTR szTable
,
300 LPCWSTR szFolder
, LPCWSTR szFilename
)
305 TRACE("%lx %s %s %s\n", handle
, debugstr_w(szTable
),
306 debugstr_w(szFolder
), debugstr_w(szFilename
));
308 db
= msihandle2msiinfo( handle
, MSIHANDLETYPE_DATABASE
);
310 return ERROR_INVALID_HANDLE
;
311 r
= MSI_DatabaseExport( db
, szTable
, szFolder
, szFilename
);
312 msiobj_release( &db
->hdr
);
316 UINT WINAPI
MsiDatabaseExportA( MSIHANDLE handle
, LPCSTR szTable
,
317 LPCSTR szFolder
, LPCSTR szFilename
)
319 LPWSTR path
= NULL
, file
= NULL
, table
= NULL
;
320 UINT r
= ERROR_OUTOFMEMORY
;
322 TRACE("%lx %s %s %s\n", handle
, debugstr_a(szTable
),
323 debugstr_a(szFolder
), debugstr_a(szFilename
));
327 table
= strdupAtoW( szTable
);
334 path
= strdupAtoW( szFolder
);
341 file
= strdupAtoW( szFilename
);
346 r
= MsiDatabaseExportW( handle
, table
, path
, file
);