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 = msi_alloc( 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 ( !IsEqualGUID( &stat
.clsid
, &CLSID_MsiDatabase
) &&
138 !IsEqualGUID( &stat
.clsid
, &CLSID_MsiPatch
) )
140 ERR("storage GUID is not a MSI database GUID %s\n",
141 debugstr_guid(&stat
.clsid
) );
145 db
= alloc_msiobject( MSIHANDLETYPE_DATABASE
, sizeof (MSIDATABASE
),
149 FIXME("Failed to allocate a handle\n");
153 if( TRACE_ON( msi
) )
154 enum_stream_names( stg
);
158 list_init( &db
->tables
);
160 db
->strings
= load_string_table( stg
);
166 msiobj_addref( &db
->hdr
);
167 IStorage_AddRef( stg
);
172 msiobj_release( &db
->hdr
);
174 IStorage_Release( stg
);
179 UINT WINAPI
MsiOpenDatabaseW(LPCWSTR szDBPath
, LPCWSTR szPersist
, MSIHANDLE
*phDB
)
184 TRACE("%s %s %p\n",debugstr_w(szDBPath
),debugstr_w(szPersist
), phDB
);
186 ret
= MSI_OpenDatabaseW( szDBPath
, szPersist
, &db
);
187 if( ret
== ERROR_SUCCESS
)
189 *phDB
= alloc_msihandle( &db
->hdr
);
190 msiobj_release( &db
->hdr
);
196 UINT WINAPI
MsiOpenDatabaseA(LPCSTR szDBPath
, LPCSTR szPersist
, MSIHANDLE
*phDB
)
198 HRESULT r
= ERROR_FUNCTION_FAILED
;
199 LPWSTR szwDBPath
= NULL
, szwPersist
= NULL
;
201 TRACE("%s %s %p\n", debugstr_a(szDBPath
), debugstr_a(szPersist
), phDB
);
205 szwDBPath
= strdupAtoW( szDBPath
);
210 if( HIWORD(szPersist
) )
212 szwPersist
= strdupAtoW( szPersist
);
217 szwPersist
= (LPWSTR
)(DWORD
)szPersist
;
219 r
= MsiOpenDatabaseW( szwDBPath
, szwPersist
, phDB
);
222 if( HIWORD(szPersist
) )
223 msi_free( szwPersist
);
224 msi_free( szwDBPath
);
229 UINT
MSI_DatabaseImport( MSIDATABASE
*db
, LPCWSTR folder
, LPCWSTR file
)
231 FIXME("%p %s %s\n", db
, debugstr_w(folder
), debugstr_w(file
) );
233 if( folder
== NULL
|| file
== NULL
)
234 return ERROR_INVALID_PARAMETER
;
236 return ERROR_CALL_NOT_IMPLEMENTED
;
239 UINT WINAPI
MsiDatabaseImportW(MSIHANDLE handle
, LPCWSTR szFolder
, LPCWSTR szFilename
)
244 TRACE("%lx %s %s\n",handle
,debugstr_w(szFolder
), debugstr_w(szFilename
));
246 db
= msihandle2msiinfo( handle
, MSIHANDLETYPE_DATABASE
);
248 return ERROR_INVALID_HANDLE
;
249 r
= MSI_DatabaseImport( db
, szFolder
, szFilename
);
250 msiobj_release( &db
->hdr
);
254 UINT WINAPI
MsiDatabaseImportA( MSIHANDLE handle
,
255 LPCSTR szFolder
, LPCSTR szFilename
)
257 LPWSTR path
= NULL
, file
= NULL
;
258 UINT r
= ERROR_OUTOFMEMORY
;
260 TRACE("%lx %s %s\n", handle
, debugstr_a(szFolder
), debugstr_a(szFilename
));
264 path
= strdupAtoW( szFolder
);
271 file
= strdupAtoW( szFilename
);
276 r
= MsiDatabaseImportW( handle
, path
, file
);
285 UINT
MSI_DatabaseExport( MSIDATABASE
*db
, LPCWSTR table
,
286 LPCWSTR folder
, LPCWSTR file
)
288 FIXME("%p %s %s %s\n", db
, debugstr_w(table
),
289 debugstr_w(folder
), debugstr_w(file
) );
291 if( folder
== NULL
|| file
== NULL
)
292 return ERROR_INVALID_PARAMETER
;
294 return ERROR_CALL_NOT_IMPLEMENTED
;
297 UINT WINAPI
MsiDatabaseExportW( MSIHANDLE handle
, LPCWSTR szTable
,
298 LPCWSTR szFolder
, LPCWSTR szFilename
)
303 TRACE("%lx %s %s %s\n", handle
, debugstr_w(szTable
),
304 debugstr_w(szFolder
), debugstr_w(szFilename
));
306 db
= msihandle2msiinfo( handle
, MSIHANDLETYPE_DATABASE
);
308 return ERROR_INVALID_HANDLE
;
309 r
= MSI_DatabaseExport( db
, szTable
, szFolder
, szFilename
);
310 msiobj_release( &db
->hdr
);
314 UINT WINAPI
MsiDatabaseExportA( MSIHANDLE handle
, LPCSTR szTable
,
315 LPCSTR szFolder
, LPCSTR szFilename
)
317 LPWSTR path
= NULL
, file
= NULL
, table
= NULL
;
318 UINT r
= ERROR_OUTOFMEMORY
;
320 TRACE("%lx %s %s %s\n", handle
, debugstr_a(szTable
),
321 debugstr_a(szFolder
), debugstr_a(szFilename
));
325 table
= strdupAtoW( szTable
);
332 path
= strdupAtoW( szFolder
);
339 file
= strdupAtoW( szFilename
);
344 r
= MsiDatabaseExportW( handle
, table
, path
, file
);