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);
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
;
67 free_cached_tables( db
);
68 msi_destroy_stringtable( db
->strings
);
69 r
= IStorage_Release( db
->storage
);
71 ERR("database reference count was not zero (%ld)\n", r
);
74 UINT
MSI_OpenDatabaseW(LPCWSTR szDBPath
, LPCWSTR szPersist
, MSIDATABASE
**pdb
)
78 MSIDATABASE
*db
= NULL
;
79 UINT ret
= ERROR_FUNCTION_FAILED
;
83 TRACE("%s %s\n",debugstr_w(szDBPath
),debugstr_w(szPersist
) );
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
);
118 ERR("unknown flag %p\n",szPersist
);
119 return ERROR_INVALID_PARAMETER
;
124 FIXME("open failed r = %08lx!\n",r
);
125 return ERROR_FUNCTION_FAILED
;
128 r
= IStorage_Stat( stg
, &stat
, STATFLAG_NONAME
);
131 FIXME("Failed to stat storage\n");
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
) );
143 db
= alloc_msiobject( MSIHANDLETYPE_DATABASE
, sizeof (MSIDATABASE
),
147 FIXME("Failed to allocate a handle\n");
151 if( TRACE_ON( msi
) )
152 enum_stream_names( stg
);
157 ret
= load_string_table( db
);
158 if( ret
!= ERROR_SUCCESS
)
161 msiobj_addref( &db
->hdr
);
162 IStorage_AddRef( stg
);
167 msiobj_release( &db
->hdr
);
169 IStorage_Release( stg
);
174 UINT WINAPI
MsiOpenDatabaseW(LPCWSTR szDBPath
, LPCWSTR szPersist
, MSIHANDLE
*phDB
)
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
);
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
);
200 szwDBPath
= strdupAtoW( szDBPath
);
205 if( HIWORD(szPersist
) )
207 szwPersist
= strdupAtoW( szPersist
);
212 szwPersist
= (LPWSTR
) szPersist
;
214 r
= MsiOpenDatabaseW( szwDBPath
, szwPersist
, phDB
);
217 if( HIWORD(szPersist
) )
218 HeapFree( GetProcessHeap(), 0, szwPersist
);
219 HeapFree( GetProcessHeap(), 0, szwDBPath
);
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
)
239 TRACE("%lx %s %s\n",handle
,debugstr_w(szFolder
), debugstr_w(szFilename
));
241 db
= msihandle2msiinfo( handle
, MSIHANDLETYPE_DATABASE
);
243 return ERROR_INVALID_HANDLE
;
244 r
= MSI_DatabaseImport( db
, szFolder
, szFilename
);
245 msiobj_release( &db
->hdr
);
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
));
259 path
= strdupAtoW( szFolder
);
266 file
= strdupAtoW( szFilename
);
271 r
= MsiDatabaseImportW( handle
, path
, file
);
274 HeapFree( GetProcessHeap(), 0, path
);
275 HeapFree( GetProcessHeap(), 0, file
);
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
)
298 TRACE("%lx %s %s %s\n", handle
, debugstr_w(szTable
),
299 debugstr_w(szFolder
), debugstr_w(szFilename
));
301 db
= msihandle2msiinfo( handle
, MSIHANDLETYPE_DATABASE
);
303 return ERROR_INVALID_HANDLE
;
304 r
= MSI_DatabaseExport( db
, szTable
, szFolder
, szFilename
);
305 msiobj_release( &db
->hdr
);
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
));
320 table
= strdupAtoW( szTable
);
327 path
= strdupAtoW( szFolder
);
334 file
= strdupAtoW( szFilename
);
339 r
= MsiDatabaseExportW( handle
, table
, path
, file
);
342 HeapFree( GetProcessHeap(), 0, table
);
343 HeapFree( GetProcessHeap(), 0, path
);
344 HeapFree( GetProcessHeap(), 0, file
);