xref: /reactos/dll/win32/msi/package.c (revision 05637a5e)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * Implementation of the Microsoft Installer (msi.dll)
3c2c66affSColin Finck  *
4c2c66affSColin Finck  * Copyright 2004 Aric Stewart for CodeWeavers
5c2c66affSColin Finck  *
6c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
7c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
8c2c66affSColin Finck  * License as published by the Free Software Foundation; either
9c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
10c2c66affSColin Finck  *
11c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
12c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14c2c66affSColin Finck  * Lesser General Public License for more details.
15c2c66affSColin Finck  *
16c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
17c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
18c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19c2c66affSColin Finck  */
20c2c66affSColin Finck 
21c42b133eSAmine Khaldi #define NONAMELESSUNION
22c42b133eSAmine Khaldi #define NONAMELESSSTRUCT
23c42b133eSAmine Khaldi #define COBJMACROS
24f4d2571bSwinesync #ifdef __REACTOS__
25f4d2571bSwinesync #define WIN32_NO_STATUS
26f4d2571bSwinesync #endif
27c2c66affSColin Finck 
28c42b133eSAmine Khaldi #include <stdarg.h>
29c42b133eSAmine Khaldi #include "windef.h"
30c42b133eSAmine Khaldi #include "winbase.h"
31c42b133eSAmine Khaldi #include "winreg.h"
32c42b133eSAmine Khaldi #include "winnls.h"
33f4d2571bSwinesync #ifdef __REACTOS__
34f4d2571bSwinesync #include <ndk/rtlfuncs.h>
35f4d2571bSwinesync #else
36f4d2571bSwinesync #include "winternl.h"
37f4d2571bSwinesync #endif
38c42b133eSAmine Khaldi #include "shlwapi.h"
39c42b133eSAmine Khaldi #include "wingdi.h"
40c42b133eSAmine Khaldi #include "msi.h"
41c42b133eSAmine Khaldi #include "msiquery.h"
42c42b133eSAmine Khaldi #include "objidl.h"
43c42b133eSAmine Khaldi #include "wincrypt.h"
44c42b133eSAmine Khaldi #include "winuser.h"
45c42b133eSAmine Khaldi #include "wininet.h"
46c42b133eSAmine Khaldi #include "winver.h"
47c42b133eSAmine Khaldi #include "urlmon.h"
48c42b133eSAmine Khaldi #include "shlobj.h"
49c42b133eSAmine Khaldi #include "objbase.h"
50c42b133eSAmine Khaldi #include "msidefs.h"
51c42b133eSAmine Khaldi #include "sddl.h"
52c42b133eSAmine Khaldi 
5362ababd7Swinesync #include "wine/debug.h"
542a9ae858Swinesync #include "wine/exception.h"
5562ababd7Swinesync 
56c42b133eSAmine Khaldi #include "msipriv.h"
57a8bc3902Swinesync #include "winemsi_s.h"
58c42b133eSAmine Khaldi #include "resource.h"
59c2c66affSColin Finck 
60c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(msi);
61c2c66affSColin Finck 
62c2c66affSColin Finck static void free_feature( MSIFEATURE *feature )
63c2c66affSColin Finck {
64c2c66affSColin Finck     struct list *item, *cursor;
65c2c66affSColin Finck 
66c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &feature->Children )
67c2c66affSColin Finck     {
68c2c66affSColin Finck         FeatureList *fl = LIST_ENTRY( item, FeatureList, entry );
69c2c66affSColin Finck         list_remove( &fl->entry );
70c2c66affSColin Finck         msi_free( fl );
71c2c66affSColin Finck     }
72c2c66affSColin Finck 
73c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &feature->Components )
74c2c66affSColin Finck     {
75c2c66affSColin Finck         ComponentList *cl = LIST_ENTRY( item, ComponentList, entry );
76c2c66affSColin Finck         list_remove( &cl->entry );
77c2c66affSColin Finck         msi_free( cl );
78c2c66affSColin Finck     }
79c2c66affSColin Finck     msi_free( feature->Feature );
80c2c66affSColin Finck     msi_free( feature->Feature_Parent );
81c2c66affSColin Finck     msi_free( feature->Directory );
82c2c66affSColin Finck     msi_free( feature->Description );
83c2c66affSColin Finck     msi_free( feature->Title );
84c2c66affSColin Finck     msi_free( feature );
85c2c66affSColin Finck }
86c2c66affSColin Finck 
87c2c66affSColin Finck static void free_folder( MSIFOLDER *folder )
88c2c66affSColin Finck {
89c2c66affSColin Finck     struct list *item, *cursor;
90c2c66affSColin Finck 
91c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &folder->children )
92c2c66affSColin Finck     {
93c2c66affSColin Finck         FolderList *fl = LIST_ENTRY( item, FolderList, entry );
94c2c66affSColin Finck         list_remove( &fl->entry );
95c2c66affSColin Finck         msi_free( fl );
96c2c66affSColin Finck     }
97c2c66affSColin Finck     msi_free( folder->Parent );
98c2c66affSColin Finck     msi_free( folder->Directory );
99c2c66affSColin Finck     msi_free( folder->TargetDefault );
100c2c66affSColin Finck     msi_free( folder->SourceLongPath );
101c2c66affSColin Finck     msi_free( folder->SourceShortPath );
102c2c66affSColin Finck     msi_free( folder->ResolvedTarget );
103c2c66affSColin Finck     msi_free( folder->ResolvedSource );
104c2c66affSColin Finck     msi_free( folder );
105c2c66affSColin Finck }
106c2c66affSColin Finck 
107c2c66affSColin Finck static void free_extension( MSIEXTENSION *ext )
108c2c66affSColin Finck {
109c2c66affSColin Finck     struct list *item, *cursor;
110c2c66affSColin Finck 
111c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &ext->verbs )
112c2c66affSColin Finck     {
113c2c66affSColin Finck         MSIVERB *verb = LIST_ENTRY( item, MSIVERB, entry );
114c2c66affSColin Finck 
115c2c66affSColin Finck         list_remove( &verb->entry );
116c2c66affSColin Finck         msi_free( verb->Verb );
117c2c66affSColin Finck         msi_free( verb->Command );
118c2c66affSColin Finck         msi_free( verb->Argument );
119c2c66affSColin Finck         msi_free( verb );
120c2c66affSColin Finck     }
121c2c66affSColin Finck 
122c2c66affSColin Finck     msi_free( ext->Extension );
123c2c66affSColin Finck     msi_free( ext->ProgIDText );
124c2c66affSColin Finck     msi_free( ext );
125c2c66affSColin Finck }
126c2c66affSColin Finck 
127c2c66affSColin Finck static void free_assembly( MSIASSEMBLY *assembly )
128c2c66affSColin Finck {
129c2c66affSColin Finck     msi_free( assembly->feature );
130c2c66affSColin Finck     msi_free( assembly->manifest );
131c2c66affSColin Finck     msi_free( assembly->application );
132c2c66affSColin Finck     msi_free( assembly->display_name );
133c2c66affSColin Finck     if (assembly->tempdir) RemoveDirectoryW( assembly->tempdir );
134c2c66affSColin Finck     msi_free( assembly->tempdir );
135c2c66affSColin Finck     msi_free( assembly );
136c2c66affSColin Finck }
137c2c66affSColin Finck 
138c2c66affSColin Finck void msi_free_action_script( MSIPACKAGE *package, UINT script )
139c2c66affSColin Finck {
140c2c66affSColin Finck     UINT i;
141f8b992f2SAmine Khaldi     for (i = 0; i < package->script_actions_count[script]; i++)
142f8b992f2SAmine Khaldi         msi_free( package->script_actions[script][i] );
143c2c66affSColin Finck 
144f8b992f2SAmine Khaldi     msi_free( package->script_actions[script] );
145f8b992f2SAmine Khaldi     package->script_actions[script] = NULL;
146f8b992f2SAmine Khaldi     package->script_actions_count[script] = 0;
147c2c66affSColin Finck }
148c2c66affSColin Finck 
149c2c66affSColin Finck static void free_package_structures( MSIPACKAGE *package )
150c2c66affSColin Finck {
151c2c66affSColin Finck     struct list *item, *cursor;
152f8b992f2SAmine Khaldi     int i;
153c2c66affSColin Finck 
154c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->features )
155c2c66affSColin Finck     {
156c2c66affSColin Finck         MSIFEATURE *feature = LIST_ENTRY( item, MSIFEATURE, entry );
157c2c66affSColin Finck         list_remove( &feature->entry );
158c2c66affSColin Finck         free_feature( feature );
159c2c66affSColin Finck     }
160c2c66affSColin Finck 
161c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->folders )
162c2c66affSColin Finck     {
163c2c66affSColin Finck         MSIFOLDER *folder = LIST_ENTRY( item, MSIFOLDER, entry );
164c2c66affSColin Finck         list_remove( &folder->entry );
165c2c66affSColin Finck         free_folder( folder );
166c2c66affSColin Finck     }
167c2c66affSColin Finck 
168c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->files )
169c2c66affSColin Finck     {
170c2c66affSColin Finck         MSIFILE *file = LIST_ENTRY( item, MSIFILE, entry );
171c2c66affSColin Finck 
172c2c66affSColin Finck         list_remove( &file->entry );
173c2c66affSColin Finck         msi_free( file->File );
174c2c66affSColin Finck         msi_free( file->FileName );
175c2c66affSColin Finck         msi_free( file->ShortName );
176c2c66affSColin Finck         msi_free( file->LongName );
177c2c66affSColin Finck         msi_free( file->Version );
178c2c66affSColin Finck         msi_free( file->Language );
179c2c66affSColin Finck         if (msi_is_global_assembly( file->Component )) DeleteFileW( file->TargetPath );
180c2c66affSColin Finck         msi_free( file->TargetPath );
181c2c66affSColin Finck         msi_free( file );
182c2c66affSColin Finck     }
183c2c66affSColin Finck 
184c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->components )
185c2c66affSColin Finck     {
186c2c66affSColin Finck         MSICOMPONENT *comp = LIST_ENTRY( item, MSICOMPONENT, entry );
187c2c66affSColin Finck 
188c2c66affSColin Finck         list_remove( &comp->entry );
189c2c66affSColin Finck         msi_free( comp->Component );
190c2c66affSColin Finck         msi_free( comp->ComponentId );
191c2c66affSColin Finck         msi_free( comp->Directory );
192c2c66affSColin Finck         msi_free( comp->Condition );
193c2c66affSColin Finck         msi_free( comp->KeyPath );
194c2c66affSColin Finck         msi_free( comp->FullKeypath );
195c2c66affSColin Finck         if (comp->assembly) free_assembly( comp->assembly );
196c2c66affSColin Finck         msi_free( comp );
197c2c66affSColin Finck     }
198c2c66affSColin Finck 
199c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->filepatches )
200c2c66affSColin Finck     {
201c2c66affSColin Finck         MSIFILEPATCH *patch = LIST_ENTRY( item, MSIFILEPATCH, entry );
202c2c66affSColin Finck 
203c2c66affSColin Finck         list_remove( &patch->entry );
204c2c66affSColin Finck         msi_free( patch->path );
205c2c66affSColin Finck         msi_free( patch );
206c2c66affSColin Finck     }
207c2c66affSColin Finck 
208c2c66affSColin Finck     /* clean up extension, progid, class and verb structures */
209c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->classes )
210c2c66affSColin Finck     {
211c2c66affSColin Finck         MSICLASS *cls = LIST_ENTRY( item, MSICLASS, entry );
212c2c66affSColin Finck 
213c2c66affSColin Finck         list_remove( &cls->entry );
214c2c66affSColin Finck         msi_free( cls->clsid );
215c2c66affSColin Finck         msi_free( cls->Context );
216c2c66affSColin Finck         msi_free( cls->Description );
217c2c66affSColin Finck         msi_free( cls->FileTypeMask );
218c2c66affSColin Finck         msi_free( cls->IconPath );
219c2c66affSColin Finck         msi_free( cls->DefInprocHandler );
220c2c66affSColin Finck         msi_free( cls->DefInprocHandler32 );
221c2c66affSColin Finck         msi_free( cls->Argument );
222c2c66affSColin Finck         msi_free( cls->ProgIDText );
223c2c66affSColin Finck         msi_free( cls );
224c2c66affSColin Finck     }
225c2c66affSColin Finck 
226c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->extensions )
227c2c66affSColin Finck     {
228c2c66affSColin Finck         MSIEXTENSION *ext = LIST_ENTRY( item, MSIEXTENSION, entry );
229c2c66affSColin Finck 
230c2c66affSColin Finck         list_remove( &ext->entry );
231c2c66affSColin Finck         free_extension( ext );
232c2c66affSColin Finck     }
233c2c66affSColin Finck 
234c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->progids )
235c2c66affSColin Finck     {
236c2c66affSColin Finck         MSIPROGID *progid = LIST_ENTRY( item, MSIPROGID, entry );
237c2c66affSColin Finck 
238c2c66affSColin Finck         list_remove( &progid->entry );
239c2c66affSColin Finck         msi_free( progid->ProgID );
240c2c66affSColin Finck         msi_free( progid->Description );
241c2c66affSColin Finck         msi_free( progid->IconPath );
242c2c66affSColin Finck         msi_free( progid );
243c2c66affSColin Finck     }
244c2c66affSColin Finck 
245c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->mimes )
246c2c66affSColin Finck     {
247c2c66affSColin Finck         MSIMIME *mt = LIST_ENTRY( item, MSIMIME, entry );
248c2c66affSColin Finck 
249c2c66affSColin Finck         list_remove( &mt->entry );
250c2c66affSColin Finck         msi_free( mt->suffix );
251c2c66affSColin Finck         msi_free( mt->clsid );
252c2c66affSColin Finck         msi_free( mt->ContentType );
253c2c66affSColin Finck         msi_free( mt );
254c2c66affSColin Finck     }
255c2c66affSColin Finck 
256c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->appids )
257c2c66affSColin Finck     {
258c2c66affSColin Finck         MSIAPPID *appid = LIST_ENTRY( item, MSIAPPID, entry );
259c2c66affSColin Finck 
260c2c66affSColin Finck         list_remove( &appid->entry );
261c2c66affSColin Finck         msi_free( appid->AppID );
262c2c66affSColin Finck         msi_free( appid->RemoteServerName );
263c2c66affSColin Finck         msi_free( appid->LocalServer );
264c2c66affSColin Finck         msi_free( appid->ServiceParameters );
265c2c66affSColin Finck         msi_free( appid->DllSurrogate );
266c2c66affSColin Finck         msi_free( appid );
267c2c66affSColin Finck     }
268c2c66affSColin Finck 
269c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_info )
270c2c66affSColin Finck     {
271c2c66affSColin Finck         MSISOURCELISTINFO *info = LIST_ENTRY( item, MSISOURCELISTINFO, entry );
272c2c66affSColin Finck 
273c2c66affSColin Finck         list_remove( &info->entry );
274c2c66affSColin Finck         msi_free( info->value );
275c2c66affSColin Finck         msi_free( info );
276c2c66affSColin Finck     }
277c2c66affSColin Finck 
278c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_media )
279c2c66affSColin Finck     {
280c2c66affSColin Finck         MSIMEDIADISK *info = LIST_ENTRY( item, MSIMEDIADISK, entry );
281c2c66affSColin Finck 
282c2c66affSColin Finck         list_remove( &info->entry );
283c2c66affSColin Finck         msi_free( info->volume_label );
284c2c66affSColin Finck         msi_free( info->disk_prompt );
285c2c66affSColin Finck         msi_free( info );
286c2c66affSColin Finck     }
287c2c66affSColin Finck 
288c2c66affSColin Finck     for (i = 0; i < SCRIPT_MAX; i++)
289c2c66affSColin Finck         msi_free_action_script( package, i );
290c2c66affSColin Finck 
291f8b992f2SAmine Khaldi     for (i = 0; i < package->unique_actions_count; i++)
292f8b992f2SAmine Khaldi         msi_free( package->unique_actions[i] );
293f8b992f2SAmine Khaldi     msi_free( package->unique_actions);
294c2c66affSColin Finck 
295c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->binaries )
296c2c66affSColin Finck     {
297c2c66affSColin Finck         MSIBINARY *binary = LIST_ENTRY( item, MSIBINARY, entry );
298c2c66affSColin Finck 
299c2c66affSColin Finck         list_remove( &binary->entry );
300c2c66affSColin Finck         if (!DeleteFileW( binary->tmpfile ))
30102f995b2Swinesync             ERR( "failed to delete %s (%lu)\n", debugstr_w(binary->tmpfile), GetLastError() );
302c2c66affSColin Finck         msi_free( binary->source );
303c2c66affSColin Finck         msi_free( binary->tmpfile );
304c2c66affSColin Finck         msi_free( binary );
305c2c66affSColin Finck     }
306c2c66affSColin Finck 
307c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->cabinet_streams )
308c2c66affSColin Finck     {
309c2c66affSColin Finck         MSICABINETSTREAM *cab = LIST_ENTRY( item, MSICABINETSTREAM, entry );
310c2c66affSColin Finck 
311c2c66affSColin Finck         list_remove( &cab->entry );
312c2c66affSColin Finck         IStorage_Release( cab->storage );
313c2c66affSColin Finck         msi_free( cab->stream );
314c2c66affSColin Finck         msi_free( cab );
315c2c66affSColin Finck     }
316c2c66affSColin Finck 
317c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->patches )
318c2c66affSColin Finck     {
319c2c66affSColin Finck         MSIPATCHINFO *patch = LIST_ENTRY( item, MSIPATCHINFO, entry );
320c2c66affSColin Finck 
321c2c66affSColin Finck         list_remove( &patch->entry );
322c2c66affSColin Finck         if (patch->delete_on_close && !DeleteFileW( patch->localfile ))
323c2c66affSColin Finck         {
32402f995b2Swinesync             ERR( "failed to delete %s (%lu)\n", debugstr_w(patch->localfile), GetLastError() );
325c2c66affSColin Finck         }
326c2c66affSColin Finck         msi_free_patchinfo( patch );
327c2c66affSColin Finck     }
328c2c66affSColin Finck 
329c2c66affSColin Finck     msi_free( package->PackagePath );
330c2c66affSColin Finck     msi_free( package->ProductCode );
331c2c66affSColin Finck     msi_free( package->ActionFormat );
332c2c66affSColin Finck     msi_free( package->LastAction );
33371bffdcdSAmine Khaldi     msi_free( package->LastActionTemplate );
334c2c66affSColin Finck     msi_free( package->langids );
335c2c66affSColin Finck 
336c2c66affSColin Finck     /* cleanup control event subscriptions */
337c2c66affSColin Finck     msi_event_cleanup_all_subscriptions( package );
338c2c66affSColin Finck }
339c2c66affSColin Finck 
340c2c66affSColin Finck static void MSI_FreePackage( MSIOBJECTHDR *arg)
341c2c66affSColin Finck {
342c2c66affSColin Finck     MSIPACKAGE *package = (MSIPACKAGE *)arg;
343c2c66affSColin Finck 
344c2c66affSColin Finck     msi_destroy_assembly_caches( package );
345c2c66affSColin Finck 
346c2c66affSColin Finck     if( package->dialog )
347c2c66affSColin Finck         msi_dialog_destroy( package->dialog );
348c2c66affSColin Finck 
349c2c66affSColin Finck     msiobj_release( &package->db->hdr );
350c2c66affSColin Finck     free_package_structures(package);
351c2c66affSColin Finck     CloseHandle( package->log_file );
3520a327bfeSwinesync     if (package->rpc_server_started)
3530a327bfeSwinesync         RpcServerUnregisterIf(s_IWineMsiRemote_v0_0_s_ifspec, NULL, FALSE);
354dfdb6d10Swinesync     if (rpc_handle)
355dfdb6d10Swinesync         RpcBindingFree(&rpc_handle);
35682decec5Swinesync     if (package->custom_server_32_process)
35782decec5Swinesync         custom_stop_server(package->custom_server_32_process, package->custom_server_32_pipe);
35882decec5Swinesync     if (package->custom_server_64_process)
35982decec5Swinesync         custom_stop_server(package->custom_server_64_process, package->custom_server_64_pipe);
360c2c66affSColin Finck 
361c2c66affSColin Finck     if (package->delete_on_close) DeleteFileW( package->localfile );
362c2c66affSColin Finck     msi_free( package->localfile );
36371bffdcdSAmine Khaldi     MSI_ProcessMessage(NULL, INSTALLMESSAGE_TERMINATE, 0);
364c2c66affSColin Finck }
365c2c66affSColin Finck 
366c2c66affSColin Finck static UINT create_temp_property_table(MSIPACKAGE *package)
367c2c66affSColin Finck {
368c2c66affSColin Finck     MSIQUERY *view;
369c2c66affSColin Finck     UINT rc;
370c2c66affSColin Finck 
3710272139cSwinesync     rc = MSI_DatabaseOpenViewW(package->db, L"CREATE TABLE `_Property` ( `_Property` CHAR(56) NOT NULL TEMPORARY, "
3720272139cSwinesync                                             L"`Value` CHAR(98) NOT NULL TEMPORARY PRIMARY KEY `_Property`) HOLD", &view);
373c2c66affSColin Finck     if (rc != ERROR_SUCCESS)
374c2c66affSColin Finck         return rc;
375c2c66affSColin Finck 
376c2c66affSColin Finck     rc = MSI_ViewExecute(view, 0);
377c2c66affSColin Finck     MSI_ViewClose(view);
378c2c66affSColin Finck     msiobj_release(&view->hdr);
379c2c66affSColin Finck     return rc;
380c2c66affSColin Finck }
381c2c66affSColin Finck 
382c2c66affSColin Finck UINT msi_clone_properties( MSIDATABASE *db )
383c2c66affSColin Finck {
384c2c66affSColin Finck     MSIQUERY *view_select;
385c2c66affSColin Finck     UINT rc;
386c2c66affSColin Finck 
3870272139cSwinesync     rc = MSI_DatabaseOpenViewW( db, L"SELECT * FROM `Property`", &view_select );
388c2c66affSColin Finck     if (rc != ERROR_SUCCESS)
389c2c66affSColin Finck         return rc;
390c2c66affSColin Finck 
391c2c66affSColin Finck     rc = MSI_ViewExecute( view_select, 0 );
392c2c66affSColin Finck     if (rc != ERROR_SUCCESS)
393c2c66affSColin Finck     {
394c2c66affSColin Finck         MSI_ViewClose( view_select );
395c2c66affSColin Finck         msiobj_release( &view_select->hdr );
396c2c66affSColin Finck         return rc;
397c2c66affSColin Finck     }
398c2c66affSColin Finck 
399c2c66affSColin Finck     while (1)
400c2c66affSColin Finck     {
401c2c66affSColin Finck         MSIQUERY *view_insert, *view_update;
402c2c66affSColin Finck         MSIRECORD *rec_select;
403c2c66affSColin Finck 
404c2c66affSColin Finck         rc = MSI_ViewFetch( view_select, &rec_select );
405c2c66affSColin Finck         if (rc != ERROR_SUCCESS)
406c2c66affSColin Finck             break;
407c2c66affSColin Finck 
4080272139cSwinesync         rc = MSI_DatabaseOpenViewW( db, L"INSERT INTO `_Property` (`_Property`,`Value`) VALUES (?,?)", &view_insert );
409c2c66affSColin Finck         if (rc != ERROR_SUCCESS)
410c2c66affSColin Finck         {
411c2c66affSColin Finck             msiobj_release( &rec_select->hdr );
412c2c66affSColin Finck             continue;
413c2c66affSColin Finck         }
414c2c66affSColin Finck 
415c2c66affSColin Finck         rc = MSI_ViewExecute( view_insert, rec_select );
416c2c66affSColin Finck         MSI_ViewClose( view_insert );
417c2c66affSColin Finck         msiobj_release( &view_insert->hdr );
418c2c66affSColin Finck         if (rc != ERROR_SUCCESS)
419c2c66affSColin Finck         {
420c2c66affSColin Finck             MSIRECORD *rec_update;
421c2c66affSColin Finck 
422c2c66affSColin Finck             TRACE("insert failed, trying update\n");
423c2c66affSColin Finck 
4240272139cSwinesync             rc = MSI_DatabaseOpenViewW( db, L"UPDATE `_Property` SET `Value` = ? WHERE `_Property` = ?", &view_update );
425c2c66affSColin Finck             if (rc != ERROR_SUCCESS)
426c2c66affSColin Finck             {
427c2c66affSColin Finck                 WARN("open view failed %u\n", rc);
428c2c66affSColin Finck                 msiobj_release( &rec_select->hdr );
429c2c66affSColin Finck                 continue;
430c2c66affSColin Finck             }
431c2c66affSColin Finck 
432c2c66affSColin Finck             rec_update = MSI_CreateRecord( 2 );
433c2c66affSColin Finck             MSI_RecordCopyField( rec_select, 1, rec_update, 2 );
434c2c66affSColin Finck             MSI_RecordCopyField( rec_select, 2, rec_update, 1 );
435c2c66affSColin Finck             rc = MSI_ViewExecute( view_update, rec_update );
436c2c66affSColin Finck             if (rc != ERROR_SUCCESS)
437c2c66affSColin Finck                 WARN("update failed %u\n", rc);
438c2c66affSColin Finck 
439c2c66affSColin Finck             MSI_ViewClose( view_update );
440c2c66affSColin Finck             msiobj_release( &view_update->hdr );
441c2c66affSColin Finck             msiobj_release( &rec_update->hdr );
442c2c66affSColin Finck         }
443c2c66affSColin Finck 
444c2c66affSColin Finck         msiobj_release( &rec_select->hdr );
445c2c66affSColin Finck     }
446c2c66affSColin Finck 
447c2c66affSColin Finck     MSI_ViewClose( view_select );
448c2c66affSColin Finck     msiobj_release( &view_select->hdr );
449c2c66affSColin Finck     return rc;
450c2c66affSColin Finck }
451c2c66affSColin Finck 
452c2c66affSColin Finck /*
453c2c66affSColin Finck  * set_installed_prop
454c2c66affSColin Finck  *
455c2c66affSColin Finck  * Sets the "Installed" property to indicate that
456c2c66affSColin Finck  *  the product is installed for the current user.
457c2c66affSColin Finck  */
458c2c66affSColin Finck static UINT set_installed_prop( MSIPACKAGE *package )
459c2c66affSColin Finck {
460c2c66affSColin Finck     HKEY hkey;
461c2c66affSColin Finck     UINT r;
462c2c66affSColin Finck 
463c2c66affSColin Finck     if (!package->ProductCode) return ERROR_FUNCTION_FAILED;
464c2c66affSColin Finck 
465c2c66affSColin Finck     r = MSIREG_OpenUninstallKey( package->ProductCode, package->platform, &hkey, FALSE );
466c2c66affSColin Finck     if (r == ERROR_SUCCESS)
467c2c66affSColin Finck     {
468c2c66affSColin Finck         RegCloseKey( hkey );
4690272139cSwinesync         msi_set_property( package->db, L"Installed", L"1", -1 );
470c2c66affSColin Finck     }
471c2c66affSColin Finck     return r;
472c2c66affSColin Finck }
473c2c66affSColin Finck 
474c2c66affSColin Finck static UINT set_user_sid_prop( MSIPACKAGE *package )
475c2c66affSColin Finck {
476c2c66affSColin Finck     SID_NAME_USE use;
477c2c66affSColin Finck     LPWSTR user_name;
478c2c66affSColin Finck     LPWSTR sid_str = NULL, dom = NULL;
479c2c66affSColin Finck     DWORD size, dom_size;
480c2c66affSColin Finck     PSID psid = NULL;
481c2c66affSColin Finck     UINT r = ERROR_FUNCTION_FAILED;
482c2c66affSColin Finck 
483c2c66affSColin Finck     size = 0;
484c2c66affSColin Finck     GetUserNameW( NULL, &size );
485c2c66affSColin Finck 
486c2c66affSColin Finck     user_name = msi_alloc( (size + 1) * sizeof(WCHAR) );
487c2c66affSColin Finck     if (!user_name)
488c2c66affSColin Finck         return ERROR_OUTOFMEMORY;
489c2c66affSColin Finck 
490c2c66affSColin Finck     if (!GetUserNameW( user_name, &size ))
491c2c66affSColin Finck         goto done;
492c2c66affSColin Finck 
493c2c66affSColin Finck     size = 0;
494c2c66affSColin Finck     dom_size = 0;
495c2c66affSColin Finck     LookupAccountNameW( NULL, user_name, NULL, &size, NULL, &dom_size, &use );
496c2c66affSColin Finck 
497c2c66affSColin Finck     psid = msi_alloc( size );
498c2c66affSColin Finck     dom = msi_alloc( dom_size*sizeof (WCHAR) );
499c2c66affSColin Finck     if (!psid || !dom)
500c2c66affSColin Finck     {
501c2c66affSColin Finck         r = ERROR_OUTOFMEMORY;
502c2c66affSColin Finck         goto done;
503c2c66affSColin Finck     }
504c2c66affSColin Finck 
505c2c66affSColin Finck     if (!LookupAccountNameW( NULL, user_name, psid, &size, dom, &dom_size, &use ))
506c2c66affSColin Finck         goto done;
507c2c66affSColin Finck 
508c2c66affSColin Finck     if (!ConvertSidToStringSidW( psid, &sid_str ))
509c2c66affSColin Finck         goto done;
510c2c66affSColin Finck 
5110272139cSwinesync     r = msi_set_property( package->db, L"UserSID", sid_str, -1 );
512c2c66affSColin Finck 
513c2c66affSColin Finck done:
514c2c66affSColin Finck     LocalFree( sid_str );
515c2c66affSColin Finck     msi_free( dom );
516c2c66affSColin Finck     msi_free( psid );
517c2c66affSColin Finck     msi_free( user_name );
518c2c66affSColin Finck 
519c2c66affSColin Finck     return r;
520c2c66affSColin Finck }
521c2c66affSColin Finck 
522c2c66affSColin Finck static LPWSTR get_fusion_filename(MSIPACKAGE *package)
523c2c66affSColin Finck {
524c42b133eSAmine Khaldi     HKEY netsetup, hkey;
525c2c66affSColin Finck     LONG res;
526c42b133eSAmine Khaldi     DWORD size, len, type;
527c42b133eSAmine Khaldi     WCHAR windir[MAX_PATH], path[MAX_PATH], *filename = NULL;
528c2c66affSColin Finck 
5290272139cSwinesync     res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\NET Framework Setup\\NDP", 0, KEY_CREATE_SUB_KEY,
5300272139cSwinesync                         &netsetup);
531c2c66affSColin Finck     if (res != ERROR_SUCCESS)
532c2c66affSColin Finck         return NULL;
533c2c66affSColin Finck 
5340272139cSwinesync     if (!RegCreateKeyExW(netsetup, L"v4\\Client", 0, NULL, 0, KEY_QUERY_VALUE, NULL, &hkey, NULL))
535c42b133eSAmine Khaldi     {
5368c1eae24Swinesync         size = sizeof(path);
5370272139cSwinesync         if (!RegQueryValueExW(hkey, L"InstallPath", NULL, &type, (BYTE *)path, &size))
538c42b133eSAmine Khaldi         {
5390272139cSwinesync             len = lstrlenW(path) + lstrlenW(L"fusion.dll") + 2;
540c42b133eSAmine Khaldi             if (!(filename = msi_alloc(len * sizeof(WCHAR)))) return NULL;
541c42b133eSAmine Khaldi 
542958f1addSwinesync             lstrcpyW(filename, path);
543a3e22d89Swinesync             lstrcatW(filename, L"\\");
5440272139cSwinesync             lstrcatW(filename, L"fusion.dll");
545c42b133eSAmine Khaldi             if (GetFileAttributesW(filename) != INVALID_FILE_ATTRIBUTES)
546c42b133eSAmine Khaldi             {
547c42b133eSAmine Khaldi                 TRACE( "found %s\n", debugstr_w(filename) );
548c42b133eSAmine Khaldi                 RegCloseKey(hkey);
549c42b133eSAmine Khaldi                 RegCloseKey(netsetup);
550c42b133eSAmine Khaldi                 return filename;
551c42b133eSAmine Khaldi             }
552c42b133eSAmine Khaldi         }
553c42b133eSAmine Khaldi         RegCloseKey(hkey);
554c42b133eSAmine Khaldi     }
555c42b133eSAmine Khaldi 
5560272139cSwinesync     if (!RegCreateKeyExW(netsetup, L"v2.0.50727", 0, NULL, 0, KEY_QUERY_VALUE, NULL, &hkey, NULL))
557c42b133eSAmine Khaldi     {
558c42b133eSAmine Khaldi         RegCloseKey(hkey);
559c2c66affSColin Finck         GetWindowsDirectoryW(windir, MAX_PATH);
5600272139cSwinesync         len = lstrlenW(windir) + lstrlenW(L"Microsoft.NET\\Framework\\") + lstrlenW(L"v2.0.50727") +
5610272139cSwinesync               lstrlenW(L"fusion.dll") + 3;
56284826781Swinesync         msi_free(filename);
563c42b133eSAmine Khaldi         if (!(filename = msi_alloc(len * sizeof(WCHAR)))) return NULL;
564c2c66affSColin Finck 
565958f1addSwinesync         lstrcpyW(filename, windir);
5660272139cSwinesync         lstrcatW(filename, L"\\");
5670272139cSwinesync         lstrcatW(filename, L"Microsoft.NET\\Framework\\");
5680272139cSwinesync         lstrcatW(filename, L"v2.0.50727");
5690272139cSwinesync         lstrcatW(filename, L"\\");
5700272139cSwinesync         lstrcatW(filename, L"fusion.dll");
571c42b133eSAmine Khaldi         if (GetFileAttributesW(filename) != INVALID_FILE_ATTRIBUTES)
572c2c66affSColin Finck         {
573c42b133eSAmine Khaldi             TRACE( "found %s\n", debugstr_w(filename) );
574c42b133eSAmine Khaldi             RegCloseKey(netsetup);
575c42b133eSAmine Khaldi             return filename;
576c2c66affSColin Finck         }
577c2c66affSColin Finck     }
578c2c66affSColin Finck 
579c2c66affSColin Finck     RegCloseKey(netsetup);
580c42b133eSAmine Khaldi     return filename;
581c2c66affSColin Finck }
582c2c66affSColin Finck 
583c2c66affSColin Finck typedef struct tagLANGANDCODEPAGE
584c2c66affSColin Finck {
585c2c66affSColin Finck   WORD wLanguage;
586c2c66affSColin Finck   WORD wCodePage;
587c2c66affSColin Finck } LANGANDCODEPAGE;
588c2c66affSColin Finck 
589c2c66affSColin Finck static void set_msi_assembly_prop(MSIPACKAGE *package)
590c2c66affSColin Finck {
591c2c66affSColin Finck     UINT val_len;
592c2c66affSColin Finck     DWORD size, handle;
593c2c66affSColin Finck     LPVOID version = NULL;
594c2c66affSColin Finck     WCHAR buf[MAX_PATH];
595c2c66affSColin Finck     LPWSTR fusion, verstr;
596c2c66affSColin Finck     LANGANDCODEPAGE *translate;
597c2c66affSColin Finck 
598c2c66affSColin Finck     fusion = get_fusion_filename(package);
599c2c66affSColin Finck     if (!fusion)
600c2c66affSColin Finck         return;
601c2c66affSColin Finck 
602c2c66affSColin Finck     size = GetFileVersionInfoSizeW(fusion, &handle);
603c2c66affSColin Finck     if (!size)
604c2c66affSColin Finck         goto done;
605c2c66affSColin Finck 
606c2c66affSColin Finck     version = msi_alloc(size);
607c2c66affSColin Finck     if (!version)
608c2c66affSColin Finck         goto done;
609c2c66affSColin Finck 
610c2c66affSColin Finck     if (!GetFileVersionInfoW(fusion, handle, size, version))
611c2c66affSColin Finck         goto done;
612c2c66affSColin Finck 
6130272139cSwinesync     if (!VerQueryValueW(version, L"\\VarFileInfo\\Translation", (LPVOID *)&translate, &val_len))
614c2c66affSColin Finck         goto done;
615c2c66affSColin Finck 
6160272139cSwinesync     swprintf(buf, ARRAY_SIZE(buf), L"\\StringFileInfo\\%04x%04x\\ProductVersion", translate[0].wLanguage,
6170272139cSwinesync              translate[0].wCodePage);
618c2c66affSColin Finck 
619c2c66affSColin Finck     if (!VerQueryValueW(version, buf, (LPVOID *)&verstr, &val_len))
620c2c66affSColin Finck         goto done;
621c2c66affSColin Finck 
622c2c66affSColin Finck     if (!val_len || !verstr)
623c2c66affSColin Finck         goto done;
624c2c66affSColin Finck 
6250272139cSwinesync     msi_set_property( package->db, L"MsiNetAssemblySupport", verstr, -1 );
626c2c66affSColin Finck 
627c2c66affSColin Finck done:
628c2c66affSColin Finck     msi_free(fusion);
629c2c66affSColin Finck     msi_free(version);
630c2c66affSColin Finck }
631c2c66affSColin Finck 
632c2c66affSColin Finck static VOID set_installer_properties(MSIPACKAGE *package)
633c2c66affSColin Finck {
634c2c66affSColin Finck     WCHAR *ptr;
635f4d2571bSwinesync     RTL_OSVERSIONINFOEXW OSVersion;
636c2c66affSColin Finck     MEMORYSTATUSEX msex;
6373ec0ea99Swinesync     DWORD verval, len, type;
638c2c66affSColin Finck     WCHAR pth[MAX_PATH], verstr[11], bufstr[22];
639c2c66affSColin Finck     HDC dc;
640c2c66affSColin Finck     HKEY hkey;
641c2c66affSColin Finck     LPWSTR username, companyname;
642c2c66affSColin Finck     SYSTEM_INFO sys_info;
643c2c66affSColin Finck     LANGID langid;
644c2c66affSColin Finck 
645c2c66affSColin Finck     /*
646c2c66affSColin Finck      * Other things that probably should be set:
647c2c66affSColin Finck      *
648c2c66affSColin Finck      * VirtualMemory ShellAdvSupport DefaultUIFont PackagecodeChanging
649c2c66affSColin Finck      * CaptionHeight BorderTop BorderSide TextHeight RedirectedDllSupport
650c2c66affSColin Finck      */
651c2c66affSColin Finck 
652c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, 0, pth);
6530272139cSwinesync     lstrcatW(pth, L"\\");
6540272139cSwinesync     msi_set_property( package->db, L"CommonAppDataFolder", pth, -1 );
655c2c66affSColin Finck 
656c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_FAVORITES, NULL, 0, pth);
6570272139cSwinesync     lstrcatW(pth, L"\\");
6580272139cSwinesync     msi_set_property( package->db, L"FavoritesFolder", pth, -1 );
659c2c66affSColin Finck 
660c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_FONTS, NULL, 0, pth);
6610272139cSwinesync     lstrcatW(pth, L"\\");
6620272139cSwinesync     msi_set_property( package->db, L"FontsFolder", pth, -1 );
663c2c66affSColin Finck 
664c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_SENDTO, NULL, 0, pth);
6650272139cSwinesync     lstrcatW(pth, L"\\");
6660272139cSwinesync     msi_set_property( package->db, L"SendToFolder", pth, -1 );
667c2c66affSColin Finck 
668c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_STARTMENU, NULL, 0, pth);
6690272139cSwinesync     lstrcatW(pth, L"\\");
6700272139cSwinesync     msi_set_property( package->db, L"StartMenuFolder", pth, -1 );
671c2c66affSColin Finck 
672c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_STARTUP, NULL, 0, pth);
6730272139cSwinesync     lstrcatW(pth, L"\\");
6740272139cSwinesync     msi_set_property( package->db, L"StartupFolder", pth, -1 );
675c2c66affSColin Finck 
676c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_TEMPLATES, NULL, 0, pth);
6770272139cSwinesync     lstrcatW(pth, L"\\");
6780272139cSwinesync     msi_set_property( package->db, L"TemplateFolder", pth, -1 );
679c2c66affSColin Finck 
680c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, pth);
6810272139cSwinesync     lstrcatW(pth, L"\\");
6820272139cSwinesync     msi_set_property( package->db, L"DesktopFolder", pth, -1 );
683c2c66affSColin Finck 
684c2c66affSColin Finck     /* FIXME: set to AllUsers profile path if ALLUSERS is set */
685c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_PROGRAMS, NULL, 0, pth);
6860272139cSwinesync     lstrcatW(pth, L"\\");
6870272139cSwinesync     msi_set_property( package->db, L"ProgramMenuFolder", pth, -1 );
688c2c66affSColin Finck 
689c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_ADMINTOOLS, NULL, 0, pth);
6900272139cSwinesync     lstrcatW(pth, L"\\");
6910272139cSwinesync     msi_set_property( package->db, L"AdminToolsFolder", pth, -1 );
692c2c66affSColin Finck 
693c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, pth);
6940272139cSwinesync     lstrcatW(pth, L"\\");
6950272139cSwinesync     msi_set_property( package->db, L"AppDataFolder", pth, -1 );
696c2c66affSColin Finck 
697c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_SYSTEM, NULL, 0, pth);
6980272139cSwinesync     lstrcatW(pth, L"\\");
6990272139cSwinesync     msi_set_property( package->db, L"SystemFolder", pth, -1 );
7000272139cSwinesync     msi_set_property( package->db, L"System16Folder", pth, -1 );
701c2c66affSColin Finck 
702c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, pth);
7030272139cSwinesync     lstrcatW(pth, L"\\");
7040272139cSwinesync     msi_set_property( package->db, L"LocalAppDataFolder", pth, -1 );
705c2c66affSColin Finck 
706c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_MYPICTURES, NULL, 0, pth);
7070272139cSwinesync     lstrcatW(pth, L"\\");
7080272139cSwinesync     msi_set_property( package->db, L"MyPicturesFolder", pth, -1 );
709c2c66affSColin Finck 
710c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, 0, pth);
7110272139cSwinesync     lstrcatW(pth, L"\\");
7120272139cSwinesync     msi_set_property( package->db, L"PersonalFolder", pth, -1 );
713c2c66affSColin Finck 
714c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth);
7150272139cSwinesync     lstrcatW(pth, L"\\");
7160272139cSwinesync     msi_set_property( package->db, L"WindowsFolder", pth, -1 );
717c2c66affSColin Finck 
718c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_PRINTHOOD, NULL, 0, pth);
7190272139cSwinesync     lstrcatW(pth, L"\\");
7200272139cSwinesync     msi_set_property( package->db, L"PrintHoodFolder", pth, -1 );
721c2c66affSColin Finck 
722c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_NETHOOD, NULL, 0, pth);
7230272139cSwinesync     lstrcatW(pth, L"\\");
7240272139cSwinesync     msi_set_property( package->db, L"NetHoodFolder", pth, -1 );
725c2c66affSColin Finck 
726c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_RECENT, NULL, 0, pth);
7270272139cSwinesync     lstrcatW(pth, L"\\");
7280272139cSwinesync     msi_set_property( package->db, L"RecentFolder", pth, -1 );
729c2c66affSColin Finck 
730c2c66affSColin Finck     /* Physical Memory is specified in MB. Using total amount. */
731c2c66affSColin Finck     msex.dwLength = sizeof(msex);
732c2c66affSColin Finck     GlobalMemoryStatusEx( &msex );
7330272139cSwinesync     len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", (int)(msex.ullTotalPhys / 1024 / 1024) );
7340272139cSwinesync     msi_set_property( package->db, L"PhysicalMemory", bufstr, len );
735c2c66affSColin Finck 
736c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth);
737958f1addSwinesync     ptr = wcschr(pth,'\\');
738c2c66affSColin Finck     if (ptr) *(ptr + 1) = 0;
7390272139cSwinesync     msi_set_property( package->db, L"WindowsVolume", pth, -1 );
740c2c66affSColin Finck 
741c2c66affSColin Finck     len = GetTempPathW(MAX_PATH, pth);
7420272139cSwinesync     msi_set_property( package->db, L"TempFolder", pth, len );
743c2c66affSColin Finck 
744c2c66affSColin Finck     /* in a wine environment the user is always admin and privileged */
7450272139cSwinesync     msi_set_property( package->db, L"AdminUser", L"1", -1 );
7460272139cSwinesync     msi_set_property( package->db, L"Privileged", L"1", -1 );
74785854456Swinesync     msi_set_property( package->db, L"MsiRunningElevated", L"1", -1 );
748c2c66affSColin Finck 
749c2c66affSColin Finck     /* set the os things */
750f4d2571bSwinesync     OSVersion.dwOSVersionInfoSize = sizeof(OSVersion);
751f4d2571bSwinesync     RtlGetVersion((PRTL_OSVERSIONINFOW)&OSVersion);
752c2c66affSColin Finck     verval = OSVersion.dwMinorVersion + OSVersion.dwMajorVersion * 100;
753f4d2571bSwinesync     if (verval > 603)
754f4d2571bSwinesync     {
755f4d2571bSwinesync         verval = 603;
756f4d2571bSwinesync         OSVersion.dwBuildNumber = 9600;
757f4d2571bSwinesync     }
7580272139cSwinesync     len = swprintf( verstr, ARRAY_SIZE(verstr), L"%u", verval );
759c2c66affSColin Finck     switch (OSVersion.dwPlatformId)
760c2c66affSColin Finck     {
761c2c66affSColin Finck         case VER_PLATFORM_WIN32_WINDOWS:
7620272139cSwinesync             msi_set_property( package->db, L"Version9X", verstr, len );
763c2c66affSColin Finck             break;
764c2c66affSColin Finck         case VER_PLATFORM_WIN32_NT:
7650272139cSwinesync             msi_set_property( package->db, L"VersionNT", verstr, len );
7660272139cSwinesync             len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%u", OSVersion.wProductType );
7670272139cSwinesync             msi_set_property( package->db, L"MsiNTProductType", bufstr, len );
768c2c66affSColin Finck             break;
769c2c66affSColin Finck     }
7700272139cSwinesync     len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%u", OSVersion.dwBuildNumber );
7710272139cSwinesync     msi_set_property( package->db, L"WindowsBuild", bufstr, len );
7720272139cSwinesync     len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%u", OSVersion.wServicePackMajor );
7730272139cSwinesync     msi_set_property( package->db, L"ServicePackLevel", bufstr, len );
774c2c66affSColin Finck 
7750272139cSwinesync     len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%u.%u", MSI_MAJORVERSION, MSI_MINORVERSION );
7760272139cSwinesync     msi_set_property( package->db, L"VersionMsi", bufstr, len );
7770272139cSwinesync     len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%u", MSI_MAJORVERSION * 100 );
7780272139cSwinesync     msi_set_property( package->db, L"VersionDatabase", bufstr, len );
779c2c66affSColin Finck 
7800272139cSwinesync     RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion", 0,
7813ec0ea99Swinesync         KEY_QUERY_VALUE | KEY_WOW64_64KEY, &hkey);
7823ec0ea99Swinesync 
783c2c66affSColin Finck     GetNativeSystemInfo( &sys_info );
7840272139cSwinesync     len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", sys_info.wProcessorLevel );
7850272139cSwinesync     msi_set_property( package->db, L"Intel", bufstr, len );
786c2c66affSColin Finck     if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
787c2c66affSColin Finck     {
788c2c66affSColin Finck         GetSystemDirectoryW( pth, MAX_PATH );
789c2c66affSColin Finck         PathAddBackslashW( pth );
7900272139cSwinesync         msi_set_property( package->db, L"SystemFolder", pth, -1 );
791c2c66affSColin Finck 
7928c1eae24Swinesync         len = sizeof(pth);
7930272139cSwinesync         RegQueryValueExW(hkey, L"ProgramFilesDir", 0, &type, (BYTE *)pth, &len);
794c2c66affSColin Finck         PathAddBackslashW( pth );
7950272139cSwinesync         msi_set_property( package->db, L"ProgramFilesFolder", pth, -1 );
796c2c66affSColin Finck 
7978c1eae24Swinesync         len = sizeof(pth);
7980272139cSwinesync         RegQueryValueExW(hkey, L"CommonFilesDir", 0, &type, (BYTE *)pth, &len);
799c2c66affSColin Finck         PathAddBackslashW( pth );
8000272139cSwinesync         msi_set_property( package->db, L"CommonFilesFolder", pth, -1 );
801c2c66affSColin Finck     }
802c2c66affSColin Finck     else if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
803c2c66affSColin Finck     {
8040272139cSwinesync         msi_set_property( package->db, L"MsiAMD64", bufstr, -1 );
8050272139cSwinesync         msi_set_property( package->db, L"Msix64", bufstr, -1 );
8060272139cSwinesync         msi_set_property( package->db, L"VersionNT64", verstr, -1 );
807c2c66affSColin Finck 
808c2c66affSColin Finck         GetSystemDirectoryW( pth, MAX_PATH );
809c2c66affSColin Finck         PathAddBackslashW( pth );
8100272139cSwinesync         msi_set_property( package->db, L"System64Folder", pth, -1 );
811c2c66affSColin Finck 
812c2c66affSColin Finck         GetSystemWow64DirectoryW( pth, MAX_PATH );
813c2c66affSColin Finck         PathAddBackslashW( pth );
8140272139cSwinesync         msi_set_property( package->db, L"SystemFolder", pth, -1 );
815c2c66affSColin Finck 
8168c1eae24Swinesync         len = sizeof(pth);
8170272139cSwinesync         RegQueryValueExW(hkey, L"ProgramFilesDir", 0, &type, (BYTE *)pth, &len);
818c2c66affSColin Finck         PathAddBackslashW( pth );
8190272139cSwinesync         msi_set_property( package->db, L"ProgramFiles64Folder", pth, -1 );
820c2c66affSColin Finck 
8218c1eae24Swinesync         len = sizeof(pth);
8220272139cSwinesync         RegQueryValueExW(hkey, L"ProgramFilesDir (x86)", 0, &type, (BYTE *)pth, &len);
823c2c66affSColin Finck         PathAddBackslashW( pth );
8240272139cSwinesync         msi_set_property( package->db, L"ProgramFilesFolder", pth, -1 );
825c2c66affSColin Finck 
8268c1eae24Swinesync         len = sizeof(pth);
8270272139cSwinesync         RegQueryValueExW(hkey, L"CommonFilesDir", 0, &type, (BYTE *)pth, &len);
828c2c66affSColin Finck         PathAddBackslashW( pth );
8290272139cSwinesync         msi_set_property( package->db, L"CommonFiles64Folder", pth, -1 );
830c2c66affSColin Finck 
8318c1eae24Swinesync         len = sizeof(pth);
8320272139cSwinesync         RegQueryValueExW(hkey, L"CommonFilesDir (x86)", 0, &type, (BYTE *)pth, &len);
833c2c66affSColin Finck         PathAddBackslashW( pth );
8340272139cSwinesync         msi_set_property( package->db, L"CommonFilesFolder", pth, -1 );
835c2c66affSColin Finck     }
836c2c66affSColin Finck 
8373ec0ea99Swinesync     RegCloseKey(hkey);
8383ec0ea99Swinesync 
839c2c66affSColin Finck     /* Screen properties. */
840c2c66affSColin Finck     dc = GetDC(0);
8410272139cSwinesync     len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", GetDeviceCaps(dc, HORZRES) );
8420272139cSwinesync     msi_set_property( package->db, L"ScreenX", bufstr, len );
8430272139cSwinesync     len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", GetDeviceCaps(dc, VERTRES) );
8440272139cSwinesync     msi_set_property( package->db, L"ScreenY", bufstr, len );
8450272139cSwinesync     len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", GetDeviceCaps(dc, BITSPIXEL) );
8460272139cSwinesync     msi_set_property( package->db, L"ColorBits", bufstr, len );
847c2c66affSColin Finck     ReleaseDC(0, dc);
848c2c66affSColin Finck 
849c2c66affSColin Finck     /* USERNAME and COMPANYNAME */
8500272139cSwinesync     username = msi_dup_property( package->db, L"USERNAME" );
8510272139cSwinesync     companyname = msi_dup_property( package->db, L"COMPANYNAME" );
852c2c66affSColin Finck 
853c2c66affSColin Finck     if ((!username || !companyname) &&
8540272139cSwinesync         RegOpenKeyW( HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\MS Setup (ACME)\\User Info", &hkey ) == ERROR_SUCCESS)
855c2c66affSColin Finck     {
856c2c66affSColin Finck         if (!username &&
8570272139cSwinesync             (username = msi_reg_get_val_str( hkey, L"DefName" )))
8580272139cSwinesync             msi_set_property( package->db, L"USERNAME", username, -1 );
859c2c66affSColin Finck         if (!companyname &&
8600272139cSwinesync             (companyname = msi_reg_get_val_str( hkey, L"DefCompany" )))
8610272139cSwinesync             msi_set_property( package->db, L"COMPANYNAME", companyname, -1 );
862c2c66affSColin Finck         CloseHandle( hkey );
863c2c66affSColin Finck     }
864c2c66affSColin Finck     if ((!username || !companyname) &&
8650272139cSwinesync         RegOpenKeyExW( HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0,
8660272139cSwinesync                        KEY_QUERY_VALUE|KEY_WOW64_64KEY, &hkey ) == ERROR_SUCCESS)
867c2c66affSColin Finck     {
868c2c66affSColin Finck         if (!username &&
8690272139cSwinesync             (username = msi_reg_get_val_str( hkey, L"RegisteredOwner" )))
8700272139cSwinesync             msi_set_property( package->db, L"USERNAME", username, -1 );
871c2c66affSColin Finck         if (!companyname &&
8720272139cSwinesync             (companyname = msi_reg_get_val_str( hkey, L"RegisteredOrganization" )))
8730272139cSwinesync             msi_set_property( package->db, L"COMPANYNAME", companyname, -1 );
874c2c66affSColin Finck         CloseHandle( hkey );
875c2c66affSColin Finck     }
876c2c66affSColin Finck     msi_free( username );
877c2c66affSColin Finck     msi_free( companyname );
878c2c66affSColin Finck 
879c2c66affSColin Finck     if ( set_user_sid_prop( package ) != ERROR_SUCCESS)
880c2c66affSColin Finck         ERR("Failed to set the UserSID property\n");
881c2c66affSColin Finck 
882c2c66affSColin Finck     set_msi_assembly_prop( package );
883c2c66affSColin Finck 
884c2c66affSColin Finck     langid = GetUserDefaultLangID();
8850272139cSwinesync     len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", langid );
8860272139cSwinesync     msi_set_property( package->db, L"UserLanguageID", bufstr, len );
887c2c66affSColin Finck 
888c2c66affSColin Finck     langid = GetSystemDefaultLangID();
8890272139cSwinesync     len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", langid );
8900272139cSwinesync     msi_set_property( package->db, L"SystemLanguageID", bufstr, len );
891c2c66affSColin Finck 
8920272139cSwinesync     len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", MsiQueryProductStateW(package->ProductCode) );
8930272139cSwinesync     msi_set_property( package->db, L"ProductState", bufstr, len );
894c2c66affSColin Finck 
895c2c66affSColin Finck     len = 0;
896c2c66affSColin Finck     if (!GetUserNameW( NULL, &len ) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
897c2c66affSColin Finck     {
898c2c66affSColin Finck         WCHAR *username;
899c2c66affSColin Finck         if ((username = msi_alloc( len * sizeof(WCHAR) )))
900c2c66affSColin Finck         {
901c2c66affSColin Finck             if (GetUserNameW( username, &len ))
9020272139cSwinesync                 msi_set_property( package->db, L"LogonUser", username, len - 1 );
903c2c66affSColin Finck             msi_free( username );
904c2c66affSColin Finck         }
905c2c66affSColin Finck     }
906c2c66affSColin Finck     len = 0;
907c2c66affSColin Finck     if (!GetComputerNameW( NULL, &len ) && GetLastError() == ERROR_BUFFER_OVERFLOW)
908c2c66affSColin Finck     {
909c2c66affSColin Finck         WCHAR *computername;
910c2c66affSColin Finck         if ((computername = msi_alloc( len * sizeof(WCHAR) )))
911c2c66affSColin Finck         {
912c2c66affSColin Finck             if (GetComputerNameW( computername, &len ))
9130272139cSwinesync                 msi_set_property( package->db, L"ComputerName", computername, len );
914c2c66affSColin Finck             msi_free( computername );
915c2c66affSColin Finck         }
916c2c66affSColin Finck     }
917c2c66affSColin Finck }
918c2c66affSColin Finck 
919c2c66affSColin Finck static MSIPACKAGE *msi_alloc_package( void )
920c2c66affSColin Finck {
921c2c66affSColin Finck     MSIPACKAGE *package;
922c2c66affSColin Finck 
923c2c66affSColin Finck     package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE),
924c2c66affSColin Finck                                MSI_FreePackage );
925c2c66affSColin Finck     if( package )
926c2c66affSColin Finck     {
927c2c66affSColin Finck         list_init( &package->components );
928c2c66affSColin Finck         list_init( &package->features );
929c2c66affSColin Finck         list_init( &package->files );
930c2c66affSColin Finck         list_init( &package->filepatches );
931c2c66affSColin Finck         list_init( &package->tempfiles );
932c2c66affSColin Finck         list_init( &package->folders );
933c2c66affSColin Finck         list_init( &package->subscriptions );
934c2c66affSColin Finck         list_init( &package->appids );
935c2c66affSColin Finck         list_init( &package->classes );
936c2c66affSColin Finck         list_init( &package->mimes );
937c2c66affSColin Finck         list_init( &package->extensions );
938c2c66affSColin Finck         list_init( &package->progids );
939c2c66affSColin Finck         list_init( &package->RunningActions );
940c2c66affSColin Finck         list_init( &package->sourcelist_info );
941c2c66affSColin Finck         list_init( &package->sourcelist_media );
942c2c66affSColin Finck         list_init( &package->patches );
943c2c66affSColin Finck         list_init( &package->binaries );
944c2c66affSColin Finck         list_init( &package->cabinet_streams );
945c2c66affSColin Finck     }
946c2c66affSColin Finck 
947c2c66affSColin Finck     return package;
948c2c66affSColin Finck }
949c2c66affSColin Finck 
950c2c66affSColin Finck static UINT msi_load_admin_properties(MSIPACKAGE *package)
951c2c66affSColin Finck {
952c2c66affSColin Finck     BYTE *data;
953c2c66affSColin Finck     UINT r, sz;
954c2c66affSColin Finck 
9550272139cSwinesync     r = read_stream_data(package->db->storage, L"AdminProperties", FALSE, &data, &sz);
956c2c66affSColin Finck     if (r != ERROR_SUCCESS)
957c2c66affSColin Finck         return r;
958c2c66affSColin Finck 
959c2c66affSColin Finck     r = msi_parse_command_line(package, (WCHAR *)data, TRUE);
960c2c66affSColin Finck 
961c2c66affSColin Finck     msi_free(data);
962c2c66affSColin Finck     return r;
963c2c66affSColin Finck }
964c2c66affSColin Finck 
965c2c66affSColin Finck void msi_adjust_privilege_properties( MSIPACKAGE *package )
966c2c66affSColin Finck {
967c2c66affSColin Finck     /* FIXME: this should depend on the user's privileges */
9680272139cSwinesync     if (msi_get_property_int( package->db, L"ALLUSERS", 0 ) == 2)
969c2c66affSColin Finck     {
970c2c66affSColin Finck         TRACE("resetting ALLUSERS property from 2 to 1\n");
9710272139cSwinesync         msi_set_property( package->db, L"ALLUSERS", L"1", -1 );
972c2c66affSColin Finck     }
9730272139cSwinesync     msi_set_property( package->db, L"AdminUser", L"1", -1 );
97485854456Swinesync     msi_set_property( package->db, L"Privileged", L"1", -1 );
97585854456Swinesync     msi_set_property( package->db, L"MsiRunningElevated", L"1", -1 );
976c2c66affSColin Finck }
977c2c66affSColin Finck 
97834c2011cSwinesync MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db )
979c2c66affSColin Finck {
980c2c66affSColin Finck     MSIPACKAGE *package;
981c2c66affSColin Finck     WCHAR uilevel[11];
982c2c66affSColin Finck     int len;
983c2c66affSColin Finck     UINT r;
984c2c66affSColin Finck 
985c2c66affSColin Finck     TRACE("%p\n", db);
986c2c66affSColin Finck 
987c2c66affSColin Finck     package = msi_alloc_package();
988c2c66affSColin Finck     if (package)
989c2c66affSColin Finck     {
990c2c66affSColin Finck         msiobj_addref( &db->hdr );
991c2c66affSColin Finck         package->db = db;
992c2c66affSColin Finck 
99371bffdcdSAmine Khaldi         package->LastAction = NULL;
99471bffdcdSAmine Khaldi         package->LastActionTemplate = NULL;
99571bffdcdSAmine Khaldi         package->LastActionResult = MSI_NULL_INTEGER;
996c2c66affSColin Finck         package->WordCount = 0;
997c2c66affSColin Finck         package->PackagePath = strdupW( db->path );
998c2c66affSColin Finck 
999c2c66affSColin Finck         create_temp_property_table( package );
1000c2c66affSColin Finck         msi_clone_properties( package->db );
1001c2c66affSColin Finck         msi_adjust_privilege_properties( package );
1002c2c66affSColin Finck 
10030272139cSwinesync         package->ProductCode = msi_dup_property( package->db, L"ProductCode" );
1004c2c66affSColin Finck 
1005c2c66affSColin Finck         set_installer_properties( package );
1006c2c66affSColin Finck 
1007c2c66affSColin Finck         package->ui_level = gUILevel;
10080272139cSwinesync         len = swprintf( uilevel, ARRAY_SIZE(uilevel), L"%u", gUILevel & INSTALLUILEVEL_MASK );
10090272139cSwinesync         msi_set_property( package->db, L"UILevel", uilevel, len );
1010c2c66affSColin Finck 
1011c2c66affSColin Finck         r = msi_load_suminfo_properties( package );
1012c2c66affSColin Finck         if (r != ERROR_SUCCESS)
1013c2c66affSColin Finck         {
1014c2c66affSColin Finck             msiobj_release( &package->hdr );
1015c2c66affSColin Finck             return NULL;
1016c2c66affSColin Finck         }
1017c2c66affSColin Finck 
1018c2c66affSColin Finck         if (package->WordCount & msidbSumInfoSourceTypeAdminImage)
1019c2c66affSColin Finck             msi_load_admin_properties( package );
1020c2c66affSColin Finck 
1021c2c66affSColin Finck         package->log_file = INVALID_HANDLE_VALUE;
10220d762dcbSwinesync         package->script = SCRIPT_NONE;
1023c2c66affSColin Finck     }
1024c2c66affSColin Finck     return package;
1025c2c66affSColin Finck }
1026c2c66affSColin Finck 
1027c2c66affSColin Finck UINT msi_download_file( LPCWSTR szUrl, LPWSTR filename )
1028c2c66affSColin Finck {
1029c2c66affSColin Finck     LPINTERNET_CACHE_ENTRY_INFOW cache_entry;
1030c2c66affSColin Finck     DWORD size = 0;
1031c2c66affSColin Finck     HRESULT hr;
1032c2c66affSColin Finck 
1033c2c66affSColin Finck     /* call will always fail, because size is 0,
1034c2c66affSColin Finck      * but will return ERROR_FILE_NOT_FOUND first
1035c2c66affSColin Finck      * if the file doesn't exist
1036c2c66affSColin Finck      */
1037c2c66affSColin Finck     GetUrlCacheEntryInfoW( szUrl, NULL, &size );
1038c2c66affSColin Finck     if ( GetLastError() != ERROR_FILE_NOT_FOUND )
1039c2c66affSColin Finck     {
1040c2c66affSColin Finck         cache_entry = msi_alloc( size );
1041c2c66affSColin Finck         if ( !GetUrlCacheEntryInfoW( szUrl, cache_entry, &size ) )
1042c2c66affSColin Finck         {
1043c2c66affSColin Finck             UINT error = GetLastError();
1044c2c66affSColin Finck             msi_free( cache_entry );
1045c2c66affSColin Finck             return error;
1046c2c66affSColin Finck         }
1047c2c66affSColin Finck 
1048c2c66affSColin Finck         lstrcpyW( filename, cache_entry->lpszLocalFileName );
1049c2c66affSColin Finck         msi_free( cache_entry );
1050c2c66affSColin Finck         return ERROR_SUCCESS;
1051c2c66affSColin Finck     }
1052c2c66affSColin Finck 
1053c2c66affSColin Finck     hr = URLDownloadToCacheFileW( NULL, szUrl, filename, MAX_PATH, 0, NULL );
1054c2c66affSColin Finck     if ( FAILED(hr) )
1055c2c66affSColin Finck     {
1056c2c66affSColin Finck         WARN("failed to download %s to cache file\n", debugstr_w(szUrl));
1057c2c66affSColin Finck         return ERROR_FUNCTION_FAILED;
1058c2c66affSColin Finck     }
1059c2c66affSColin Finck 
1060c2c66affSColin Finck     return ERROR_SUCCESS;
1061c2c66affSColin Finck }
1062c2c66affSColin Finck 
1063c2c66affSColin Finck UINT msi_create_empty_local_file( LPWSTR path, LPCWSTR suffix )
1064c2c66affSColin Finck {
1065c2c66affSColin Finck     DWORD time, len, i, offset;
1066c2c66affSColin Finck     HANDLE handle;
1067c2c66affSColin Finck 
1068c2c66affSColin Finck     time = GetTickCount();
1069c2c66affSColin Finck     GetWindowsDirectoryW( path, MAX_PATH );
10700272139cSwinesync     lstrcatW( path, L"\\Installer\\" );
1071c2c66affSColin Finck     CreateDirectoryW( path, NULL );
1072c2c66affSColin Finck 
1073958f1addSwinesync     len = lstrlenW(path);
1074c2c66affSColin Finck     for (i = 0; i < 0x10000; i++)
1075c2c66affSColin Finck     {
10760272139cSwinesync         offset = swprintf( path + len, MAX_PATH - len, L"%x", (time + i) & 0xffff );
1077958f1addSwinesync         memcpy( path + len + offset, suffix, (lstrlenW( suffix ) + 1) * sizeof(WCHAR) );
1078c2c66affSColin Finck         handle = CreateFileW( path, GENERIC_WRITE, 0, NULL,
1079c2c66affSColin Finck                               CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
1080c2c66affSColin Finck         if (handle != INVALID_HANDLE_VALUE)
1081c2c66affSColin Finck         {
1082c2c66affSColin Finck             CloseHandle(handle);
1083c2c66affSColin Finck             break;
1084c2c66affSColin Finck         }
1085c2c66affSColin Finck         if (GetLastError() != ERROR_FILE_EXISTS &&
1086c2c66affSColin Finck             GetLastError() != ERROR_SHARING_VIOLATION)
1087c2c66affSColin Finck             return ERROR_FUNCTION_FAILED;
1088c2c66affSColin Finck     }
1089c2c66affSColin Finck 
1090c2c66affSColin Finck     return ERROR_SUCCESS;
1091c2c66affSColin Finck }
1092c2c66affSColin Finck 
1093c2c66affSColin Finck static enum platform parse_platform( const WCHAR *str )
1094c2c66affSColin Finck {
10950272139cSwinesync     if (!str[0] || !wcscmp( str, L"Intel" )) return PLATFORM_INTEL;
10960272139cSwinesync     else if (!wcscmp( str, L"Intel64" )) return PLATFORM_INTEL64;
10970272139cSwinesync     else if (!wcscmp( str, L"x64" ) || !wcscmp( str, L"AMD64" )) return PLATFORM_X64;
10980272139cSwinesync     else if (!wcscmp( str, L"Arm" )) return PLATFORM_ARM;
10990272139cSwinesync     else if (!wcscmp( str, L"Arm64" )) return PLATFORM_ARM64;
110098d8ddaaSwinesync     return PLATFORM_UNRECOGNIZED;
1101c2c66affSColin Finck }
1102c2c66affSColin Finck 
1103c2c66affSColin Finck static UINT parse_suminfo( MSISUMMARYINFO *si, MSIPACKAGE *package )
1104c2c66affSColin Finck {
1105c2c66affSColin Finck     WCHAR *template, *p, *q, *platform;
1106c2c66affSColin Finck     DWORD i, count;
1107c2c66affSColin Finck 
1108c2c66affSColin Finck     package->version = msi_suminfo_get_int32( si, PID_PAGECOUNT );
1109c2c66affSColin Finck     TRACE("version: %d\n", package->version);
1110c2c66affSColin Finck 
1111c2c66affSColin Finck     template = msi_suminfo_dup_string( si, PID_TEMPLATE );
1112c2c66affSColin Finck     if (!template)
1113c2c66affSColin Finck         return ERROR_SUCCESS; /* native accepts missing template property */
1114c2c66affSColin Finck 
1115c2c66affSColin Finck     TRACE("template: %s\n", debugstr_w(template));
1116c2c66affSColin Finck 
1117958f1addSwinesync     p = wcschr( template, ';' );
1118c2c66affSColin Finck     if (!p)
1119c2c66affSColin Finck     {
1120c2c66affSColin Finck         WARN("invalid template string %s\n", debugstr_w(template));
1121c2c66affSColin Finck         msi_free( template );
1122c2c66affSColin Finck         return ERROR_PATCH_PACKAGE_INVALID;
1123c2c66affSColin Finck     }
1124c2c66affSColin Finck     *p = 0;
1125c2c66affSColin Finck     platform = template;
1126958f1addSwinesync     if ((q = wcschr( platform, ',' ))) *q = 0;
1127c2c66affSColin Finck     package->platform = parse_platform( platform );
112898d8ddaaSwinesync     while (package->platform == PLATFORM_UNRECOGNIZED && q)
1129c2c66affSColin Finck     {
1130c2c66affSColin Finck         platform = q + 1;
1131958f1addSwinesync         if ((q = wcschr( platform, ',' ))) *q = 0;
1132c2c66affSColin Finck         package->platform = parse_platform( platform );
1133c2c66affSColin Finck     }
113498d8ddaaSwinesync     if (package->platform == PLATFORM_UNRECOGNIZED)
1135c2c66affSColin Finck     {
1136c2c66affSColin Finck         WARN("unknown platform %s\n", debugstr_w(template));
1137c2c66affSColin Finck         msi_free( template );
1138c2c66affSColin Finck         return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
1139c2c66affSColin Finck     }
1140c2c66affSColin Finck     p++;
1141c2c66affSColin Finck     if (!*p)
1142c2c66affSColin Finck     {
1143c2c66affSColin Finck         msi_free( template );
1144c2c66affSColin Finck         return ERROR_SUCCESS;
1145c2c66affSColin Finck     }
1146c2c66affSColin Finck     count = 1;
1147958f1addSwinesync     for (q = p; (q = wcschr( q, ',' )); q++) count++;
1148c2c66affSColin Finck 
1149c2c66affSColin Finck     package->langids = msi_alloc( count * sizeof(LANGID) );
1150c2c66affSColin Finck     if (!package->langids)
1151c2c66affSColin Finck     {
1152c2c66affSColin Finck         msi_free( template );
1153c2c66affSColin Finck         return ERROR_OUTOFMEMORY;
1154c2c66affSColin Finck     }
1155c2c66affSColin Finck 
1156c2c66affSColin Finck     i = 0;
1157c2c66affSColin Finck     while (*p)
1158c2c66affSColin Finck     {
1159958f1addSwinesync         q = wcschr( p, ',' );
1160c2c66affSColin Finck         if (q) *q = 0;
1161958f1addSwinesync         package->langids[i] = wcstol( p, NULL, 10 );
1162c2c66affSColin Finck         if (!q) break;
1163c2c66affSColin Finck         p = q + 1;
1164c2c66affSColin Finck         i++;
1165c2c66affSColin Finck     }
1166c2c66affSColin Finck     package->num_langids = i + 1;
1167c2c66affSColin Finck 
1168c2c66affSColin Finck     msi_free( template );
1169c2c66affSColin Finck     return ERROR_SUCCESS;
1170c2c66affSColin Finck }
1171c2c66affSColin Finck 
1172c2c66affSColin Finck static UINT validate_package( MSIPACKAGE *package )
1173c2c66affSColin Finck {
1174c2c66affSColin Finck     UINT i;
1175c2c66affSColin Finck 
1176c2c66affSColin Finck     if (package->platform == PLATFORM_INTEL64)
1177c2c66affSColin Finck         return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
1178c2c66affSColin Finck #ifndef __arm__
1179c2c66affSColin Finck     if (package->platform == PLATFORM_ARM)
1180c2c66affSColin Finck         return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
1181c2c66affSColin Finck #endif
1182de59794fSwinesync #ifndef __aarch64__
1183de59794fSwinesync     if (package->platform == PLATFORM_ARM64)
1184de59794fSwinesync         return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
1185de59794fSwinesync #endif
1186c2c66affSColin Finck     if (package->platform == PLATFORM_X64)
1187c2c66affSColin Finck     {
1188c2c66affSColin Finck         if (!is_64bit && !is_wow64)
1189c2c66affSColin Finck             return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
1190c2c66affSColin Finck         if (package->version < 200)
1191c2c66affSColin Finck             return ERROR_INSTALL_PACKAGE_INVALID;
1192c2c66affSColin Finck     }
1193c2c66affSColin Finck     if (!package->num_langids)
1194c2c66affSColin Finck     {
1195c2c66affSColin Finck         return ERROR_SUCCESS;
1196c2c66affSColin Finck     }
1197c2c66affSColin Finck     for (i = 0; i < package->num_langids; i++)
1198c2c66affSColin Finck     {
1199c2c66affSColin Finck         LANGID langid = package->langids[i];
1200c2c66affSColin Finck 
1201c2c66affSColin Finck         if (PRIMARYLANGID( langid ) == LANG_NEUTRAL)
1202c2c66affSColin Finck         {
1203c2c66affSColin Finck             langid = MAKELANGID( PRIMARYLANGID( GetSystemDefaultLangID() ), SUBLANGID( langid ) );
1204c2c66affSColin Finck         }
1205c2c66affSColin Finck         if (SUBLANGID( langid ) == SUBLANG_NEUTRAL)
1206c2c66affSColin Finck         {
1207c2c66affSColin Finck             langid = MAKELANGID( PRIMARYLANGID( langid ), SUBLANGID( GetSystemDefaultLangID() ) );
1208c2c66affSColin Finck         }
1209c2c66affSColin Finck         if (IsValidLocale( langid, LCID_INSTALLED ))
1210c2c66affSColin Finck             return ERROR_SUCCESS;
1211c2c66affSColin Finck     }
1212c2c66affSColin Finck     return ERROR_INSTALL_LANGUAGE_UNSUPPORTED;
1213c2c66affSColin Finck }
1214c2c66affSColin Finck 
1215b7b9c0c4Swinesync static WCHAR *get_property( MSIDATABASE *db, const WCHAR *prop )
1216c2c66affSColin Finck {
1217b7b9c0c4Swinesync     WCHAR query[MAX_PATH];
1218c2c66affSColin Finck     MSIQUERY *view;
1219c2c66affSColin Finck     MSIRECORD *rec;
1220c2c66affSColin Finck     WCHAR *ret = NULL;
1221c2c66affSColin Finck 
12220272139cSwinesync     swprintf(query, ARRAY_SIZE(query), L"SELECT `Value` FROM `Property` WHERE `Property`='%s'", prop);
1223c2c66affSColin Finck     if (MSI_DatabaseOpenViewW( db, query, &view ) != ERROR_SUCCESS)
1224c2c66affSColin Finck     {
1225c2c66affSColin Finck         return NULL;
1226c2c66affSColin Finck     }
1227c2c66affSColin Finck     if (MSI_ViewExecute( view, 0 ) != ERROR_SUCCESS)
1228c2c66affSColin Finck     {
1229c2c66affSColin Finck         MSI_ViewClose( view );
1230c2c66affSColin Finck         msiobj_release( &view->hdr );
1231c2c66affSColin Finck         return NULL;
1232c2c66affSColin Finck     }
1233c2c66affSColin Finck     if (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS)
1234c2c66affSColin Finck     {
1235c2c66affSColin Finck         ret = strdupW( MSI_RecordGetString( rec, 1 ) );
1236c2c66affSColin Finck         msiobj_release( &rec->hdr );
1237c2c66affSColin Finck     }
1238c2c66affSColin Finck     MSI_ViewClose( view );
1239c2c66affSColin Finck     msiobj_release( &view->hdr );
1240c2c66affSColin Finck     return ret;
1241c2c66affSColin Finck }
1242c2c66affSColin Finck 
1243b7b9c0c4Swinesync static WCHAR *get_product_code( MSIDATABASE *db )
1244b7b9c0c4Swinesync {
12450272139cSwinesync     return get_property( db, L"ProductCode" );
1246b7b9c0c4Swinesync }
1247b7b9c0c4Swinesync 
1248b7b9c0c4Swinesync static WCHAR *get_product_version( MSIDATABASE *db )
1249b7b9c0c4Swinesync {
12500272139cSwinesync     return get_property( db, L"ProductVersion" );
1251b7b9c0c4Swinesync }
1252b7b9c0c4Swinesync 
1253b7b9c0c4Swinesync static UINT get_registered_local_package( const WCHAR *product, WCHAR *localfile )
1254c2c66affSColin Finck {
1255c2c66affSColin Finck     MSIINSTALLCONTEXT context;
1256b7b9c0c4Swinesync     WCHAR *filename;
1257b7b9c0c4Swinesync     HKEY props_key;
1258c2c66affSColin Finck     UINT r;
1259c2c66affSColin Finck 
1260c2c66affSColin Finck     r = msi_locate_product( product, &context );
1261c2c66affSColin Finck     if (r != ERROR_SUCCESS)
1262c2c66affSColin Finck         return r;
1263c2c66affSColin Finck 
1264c2c66affSColin Finck     r = MSIREG_OpenInstallProps( product, context, NULL, &props_key, FALSE );
1265c2c66affSColin Finck     if (r != ERROR_SUCCESS)
1266c2c66affSColin Finck         return r;
1267c2c66affSColin Finck 
1268b7b9c0c4Swinesync     filename = msi_reg_get_val_str( props_key, INSTALLPROPERTY_LOCALPACKAGEW );
1269b7b9c0c4Swinesync     RegCloseKey( props_key );
1270c2c66affSColin Finck     if (!filename)
1271b7b9c0c4Swinesync         return ERROR_FUNCTION_FAILED;
1272c2c66affSColin Finck 
1273958f1addSwinesync     lstrcpyW( localfile, filename );
1274c2c66affSColin Finck     msi_free( filename );
1275b7b9c0c4Swinesync     return ERROR_SUCCESS;
1276c2c66affSColin Finck }
1277c2c66affSColin Finck 
127874196b80Swinesync WCHAR *msi_get_package_code( MSIDATABASE *db )
1279c2c66affSColin Finck {
1280c2c66affSColin Finck     WCHAR *ret;
1281c2c66affSColin Finck     MSISUMMARYINFO *si;
1282c2c66affSColin Finck     UINT r;
1283c2c66affSColin Finck 
1284c2c66affSColin Finck     r = msi_get_suminfo( db->storage, 0, &si );
1285c2c66affSColin Finck     if (r != ERROR_SUCCESS)
1286c2c66affSColin Finck     {
1287c2c66affSColin Finck         r = msi_get_db_suminfo( db, 0, &si );
1288c2c66affSColin Finck         if (r != ERROR_SUCCESS)
1289c2c66affSColin Finck         {
1290c2c66affSColin Finck             WARN("failed to load summary info %u\n", r);
1291c2c66affSColin Finck             return NULL;
1292c2c66affSColin Finck         }
1293c2c66affSColin Finck     }
1294c2c66affSColin Finck     ret = msi_suminfo_dup_string( si, PID_REVNUMBER );
1295c2c66affSColin Finck     msiobj_release( &si->hdr );
1296c2c66affSColin Finck     return ret;
1297c2c66affSColin Finck }
1298c2c66affSColin Finck 
1299b7b9c0c4Swinesync static UINT get_local_package( MSIDATABASE *db, WCHAR *localfile )
1300c2c66affSColin Finck {
1301b7b9c0c4Swinesync     WCHAR *product_code;
1302c2c66affSColin Finck     UINT r;
1303c2c66affSColin Finck 
1304c2c66affSColin Finck     if (!(product_code = get_product_code( db )))
1305c2c66affSColin Finck         return ERROR_INSTALL_PACKAGE_INVALID;
1306b7b9c0c4Swinesync     r = get_registered_local_package( product_code, localfile );
1307c2c66affSColin Finck     msi_free( product_code );
1308c2c66affSColin Finck     return r;
1309c2c66affSColin Finck }
1310c2c66affSColin Finck 
1311c2c66affSColin Finck UINT msi_set_original_database_property( MSIDATABASE *db, const WCHAR *package )
1312c2c66affSColin Finck {
1313c2c66affSColin Finck     UINT r;
1314c2c66affSColin Finck 
1315c2c66affSColin Finck     if (UrlIsW( package, URLIS_URL ))
13160272139cSwinesync         r = msi_set_property( db, L"OriginalDatabase", package, -1 );
1317c2c66affSColin Finck     else if (package[0] == '#')
13180272139cSwinesync         r = msi_set_property( db, L"OriginalDatabase", db->path, -1 );
1319c2c66affSColin Finck     else
1320c2c66affSColin Finck     {
1321c2c66affSColin Finck         DWORD len;
1322c2c66affSColin Finck         WCHAR *path;
1323c2c66affSColin Finck 
1324c2c66affSColin Finck         if (!(len = GetFullPathNameW( package, 0, NULL, NULL ))) return GetLastError();
1325c2c66affSColin Finck         if (!(path = msi_alloc( len * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY;
1326c2c66affSColin Finck         len = GetFullPathNameW( package, len, path, NULL );
13270272139cSwinesync         r = msi_set_property( db, L"OriginalDatabase", path, len );
1328c2c66affSColin Finck         msi_free( path );
1329c2c66affSColin Finck     }
1330c2c66affSColin Finck     return r;
1331c2c66affSColin Finck }
1332c2c66affSColin Finck 
1333*05637a5eSMark Jansen #ifdef __REACTOS__
1334*05637a5eSMark Jansen BOOL WINAPI ApphelpCheckRunAppEx(HANDLE FileHandle, PVOID Unk1, PVOID Unk2, PCWSTR ApplicationName, PVOID Environment, USHORT ExeType, PULONG Reason, PVOID *SdbQueryAppCompatData, PULONG SdbQueryAppCompatDataSize,
1335*05637a5eSMark Jansen     PVOID *SxsData, PULONG SxsDataSize, PULONG FusionFlags, PULONG64 SomeFlag1, PULONG SomeFlag2);
1336*05637a5eSMark Jansen BOOL WINAPI SE_DynamicShim(LPCWSTR ProcessImage, PVOID hsdb, PVOID pQueryResult, LPCSTR Module, LPDWORD lpdwDynamicToken);
1337*05637a5eSMark Jansen PVOID WINAPI SdbInitDatabase(DWORD flags, LPCWSTR path);
1338*05637a5eSMark Jansen PVOID WINAPI SdbReleaseDatabase(PVOID hsdb);
1339*05637a5eSMark Jansen 
1340*05637a5eSMark Jansen #define HID_DOS_PATHS 0x1
1341*05637a5eSMark Jansen #define SDB_DATABASE_MAIN_SHIM 0x80030000
1342*05637a5eSMark Jansen 
1343*05637a5eSMark Jansen #define APPHELP_VALID_RESULT 0x10000
1344*05637a5eSMark Jansen #define APPHELP_RESULT_FOUND 0x40000
1345*05637a5eSMark Jansen 
1346*05637a5eSMark Jansen static void
1347*05637a5eSMark Jansen AppHelpCheckPackage(LPCWSTR szPackage)
1348*05637a5eSMark Jansen {
1349*05637a5eSMark Jansen     USHORT ExeType = 0;
1350*05637a5eSMark Jansen     ULONG Reason = 0;
1351*05637a5eSMark Jansen 
1352*05637a5eSMark Jansen     PVOID QueryResult = NULL;
1353*05637a5eSMark Jansen     ULONG QueryResultSize = 0;
1354*05637a5eSMark Jansen 
1355*05637a5eSMark Jansen     HANDLE Handle = NULL;
1356*05637a5eSMark Jansen     BOOL Continue = ApphelpCheckRunAppEx(
1357*05637a5eSMark Jansen         Handle, NULL, NULL, szPackage, NULL, ExeType, &Reason, &QueryResult, &QueryResultSize, NULL,
1358*05637a5eSMark Jansen         NULL, NULL, NULL, NULL);
1359*05637a5eSMark Jansen 
1360*05637a5eSMark Jansen     if (Continue)
1361*05637a5eSMark Jansen     {
1362*05637a5eSMark Jansen         if ((Reason & (APPHELP_VALID_RESULT | APPHELP_RESULT_FOUND)) == (APPHELP_VALID_RESULT | APPHELP_RESULT_FOUND))
1363*05637a5eSMark Jansen         {
1364*05637a5eSMark Jansen             DWORD dwToken;
1365*05637a5eSMark Jansen             PVOID hsdb = SdbInitDatabase(HID_DOS_PATHS | SDB_DATABASE_MAIN_SHIM, NULL);
1366*05637a5eSMark Jansen             if (hsdb)
1367*05637a5eSMark Jansen             {
1368*05637a5eSMark Jansen                 BOOL bShim = SE_DynamicShim(szPackage, hsdb, QueryResult, "msi.dll", &dwToken);
1369*05637a5eSMark Jansen                 ERR("ReactOS HACK: Used SE_DynamicShim %d!\n", bShim);
1370*05637a5eSMark Jansen 
1371*05637a5eSMark Jansen                 SdbReleaseDatabase(hsdb);
1372*05637a5eSMark Jansen             }
1373*05637a5eSMark Jansen             else
1374*05637a5eSMark Jansen             {
1375*05637a5eSMark Jansen                 ERR("Unable to open SDB_DATABASE_MAIN_SHIM\n");
1376*05637a5eSMark Jansen             }
1377*05637a5eSMark Jansen         }
1378*05637a5eSMark Jansen     }
1379*05637a5eSMark Jansen 
1380*05637a5eSMark Jansen     if (QueryResult)
1381*05637a5eSMark Jansen         RtlFreeHeap(RtlGetProcessHeap(), 0, QueryResult);
1382*05637a5eSMark Jansen }
1383*05637a5eSMark Jansen #endif
1384*05637a5eSMark Jansen 
1385a2371385Swinesync UINT MSI_OpenPackageW(LPCWSTR szPackage, DWORD dwOptions, MSIPACKAGE **pPackage)
1386c2c66affSColin Finck {
1387c2c66affSColin Finck     MSIDATABASE *db;
1388c2c66affSColin Finck     MSIPACKAGE *package;
1389c2c66affSColin Finck     MSIHANDLE handle;
139071bffdcdSAmine Khaldi     MSIRECORD *data_row, *info_row;
1391c2c66affSColin Finck     UINT r;
1392c2c66affSColin Finck     WCHAR localfile[MAX_PATH], cachefile[MAX_PATH];
1393c2c66affSColin Finck     LPCWSTR file = szPackage;
1394c2c66affSColin Finck     DWORD index = 0;
1395c2c66affSColin Finck     MSISUMMARYINFO *si;
1396c2c66affSColin Finck     BOOL delete_on_close = FALSE;
1397da848361Swinesync     WCHAR *info_template, *productname, *product_code;
1398da848361Swinesync     MSIINSTALLCONTEXT context;
1399c2c66affSColin Finck 
1400c2c66affSColin Finck     TRACE("%s %p\n", debugstr_w(szPackage), pPackage);
1401c2c66affSColin Finck 
140271bffdcdSAmine Khaldi     MSI_ProcessMessage(NULL, INSTALLMESSAGE_INITIALIZE, 0);
140371bffdcdSAmine Khaldi 
1404c2c66affSColin Finck     localfile[0] = 0;
1405c2c66affSColin Finck     if( szPackage[0] == '#' )
1406c2c66affSColin Finck     {
1407958f1addSwinesync         handle = wcstol(&szPackage[1], NULL, 10);
1408b720e4c0Swinesync         if (!(db = msihandle2msiinfo(handle, MSIHANDLETYPE_DATABASE)))
1409c2c66affSColin Finck             return ERROR_INVALID_HANDLE;
1410c2c66affSColin Finck     }
1411c2c66affSColin Finck     else
1412c2c66affSColin Finck     {
1413b7b9c0c4Swinesync         WCHAR *product_version = NULL;
1414b7b9c0c4Swinesync 
1415c2c66affSColin Finck         if ( UrlIsW( szPackage, URLIS_URL ) )
1416c2c66affSColin Finck         {
1417c2c66affSColin Finck             r = msi_download_file( szPackage, cachefile );
1418c2c66affSColin Finck             if (r != ERROR_SUCCESS)
1419c2c66affSColin Finck                 return r;
1420c2c66affSColin Finck 
1421c2c66affSColin Finck             file = cachefile;
1422c2c66affSColin Finck         }
1423*05637a5eSMark Jansen #ifdef __REACTOS__
1424*05637a5eSMark Jansen         AppHelpCheckPackage(file);
1425*05637a5eSMark Jansen #endif
1426*05637a5eSMark Jansen 
1427b7b9c0c4Swinesync         r = MSI_OpenDatabaseW( file, MSIDBOPEN_READONLY, &db );
1428b7b9c0c4Swinesync         if (r != ERROR_SUCCESS)
1429b7b9c0c4Swinesync         {
1430b7b9c0c4Swinesync             if (GetFileAttributesW( file ) == INVALID_FILE_ATTRIBUTES)
1431b7b9c0c4Swinesync                 return ERROR_FILE_NOT_FOUND;
1432b7b9c0c4Swinesync             return r;
1433b7b9c0c4Swinesync         }
1434b7b9c0c4Swinesync         r = get_local_package( db, localfile );
1435c2c66affSColin Finck         if (r != ERROR_SUCCESS || GetFileAttributesW( localfile ) == INVALID_FILE_ATTRIBUTES)
1436c2c66affSColin Finck         {
143763bb43adSJérôme Gardou             DWORD localfile_attr;
143863bb43adSJérôme Gardou 
14390272139cSwinesync             r = msi_create_empty_local_file( localfile, L".msi" );
1440c2c66affSColin Finck             if (r != ERROR_SUCCESS)
1441b7b9c0c4Swinesync             {
1442b7b9c0c4Swinesync                 msiobj_release( &db->hdr );
1443c2c66affSColin Finck                 return r;
1444b7b9c0c4Swinesync             }
1445c2c66affSColin Finck 
1446c2c66affSColin Finck             if (!CopyFileW( file, localfile, FALSE ))
1447c2c66affSColin Finck             {
1448c2c66affSColin Finck                 r = GetLastError();
1449c2c66affSColin Finck                 WARN("unable to copy package %s to %s (%u)\n", debugstr_w(file), debugstr_w(localfile), r);
1450c2c66affSColin Finck                 DeleteFileW( localfile );
1451b7b9c0c4Swinesync                 msiobj_release( &db->hdr );
1452c2c66affSColin Finck                 return r;
1453c2c66affSColin Finck             }
1454c2c66affSColin Finck             delete_on_close = TRUE;
145563bb43adSJérôme Gardou 
145663bb43adSJérôme Gardou             /* Remove read-only bit, we are opening it with write access in MSI_OpenDatabaseW below. */
145763bb43adSJérôme Gardou             localfile_attr = GetFileAttributesW( localfile );
145863bb43adSJérôme Gardou             if (localfile_attr & FILE_ATTRIBUTE_READONLY)
145963bb43adSJérôme Gardou                 SetFileAttributesW( localfile, localfile_attr & ~FILE_ATTRIBUTE_READONLY);
1460c2c66affSColin Finck         }
1461a2371385Swinesync         else if (dwOptions & WINE_OPENPACKAGEFLAGS_RECACHE)
1462a2371385Swinesync         {
1463a2371385Swinesync             if (!CopyFileW( file, localfile, FALSE ))
1464a2371385Swinesync             {
1465a2371385Swinesync                 r = GetLastError();
1466a2371385Swinesync                 WARN("unable to update cached package (%u)\n", r);
1467a2371385Swinesync                 msiobj_release( &db->hdr );
1468a2371385Swinesync                 return r;
1469a2371385Swinesync             }
1470a2371385Swinesync         }
1471b7b9c0c4Swinesync         else
1472b7b9c0c4Swinesync             product_version = get_product_version( db );
1473b7b9c0c4Swinesync         msiobj_release( &db->hdr );
1474c2c66affSColin Finck         TRACE("opening package %s\n", debugstr_w( localfile ));
1475c2c66affSColin Finck         r = MSI_OpenDatabaseW( localfile, MSIDBOPEN_TRANSACT, &db );
1476c2c66affSColin Finck         if (r != ERROR_SUCCESS)
1477c2c66affSColin Finck             return r;
1478b7b9c0c4Swinesync 
1479b7b9c0c4Swinesync         if (product_version)
1480b7b9c0c4Swinesync         {
1481b7b9c0c4Swinesync             WCHAR *cache_version = get_product_version( db );
1482b7b9c0c4Swinesync             if (!product_version != !cache_version ||
1483958f1addSwinesync                     (product_version && wcscmp(product_version, cache_version)))
1484b7b9c0c4Swinesync             {
1485b7b9c0c4Swinesync                 msiobj_release( &db->hdr );
1486b7b9c0c4Swinesync                 msi_free(product_version);
1487b7b9c0c4Swinesync                 msi_free(cache_version);
1488b7b9c0c4Swinesync                 return ERROR_PRODUCT_VERSION;
1489b7b9c0c4Swinesync             }
1490b7b9c0c4Swinesync             msi_free(product_version);
1491b7b9c0c4Swinesync             msi_free(cache_version);
1492b7b9c0c4Swinesync         }
1493c2c66affSColin Finck     }
149434c2011cSwinesync     package = MSI_CreatePackage( db );
1495c2c66affSColin Finck     msiobj_release( &db->hdr );
1496c2c66affSColin Finck     if (!package) return ERROR_INSTALL_PACKAGE_INVALID;
1497c2c66affSColin Finck     package->localfile = strdupW( localfile );
1498c2c66affSColin Finck     package->delete_on_close = delete_on_close;
1499c2c66affSColin Finck 
1500c2c66affSColin Finck     r = msi_get_suminfo( db->storage, 0, &si );
1501c2c66affSColin Finck     if (r != ERROR_SUCCESS)
1502c2c66affSColin Finck     {
1503c2c66affSColin Finck         r = msi_get_db_suminfo( db, 0, &si );
1504c2c66affSColin Finck         if (r != ERROR_SUCCESS)
1505c2c66affSColin Finck         {
1506c2c66affSColin Finck             WARN("failed to load summary info\n");
1507c2c66affSColin Finck             msiobj_release( &package->hdr );
1508c2c66affSColin Finck             return ERROR_INSTALL_PACKAGE_INVALID;
1509c2c66affSColin Finck         }
1510c2c66affSColin Finck     }
1511c2c66affSColin Finck     r = parse_suminfo( si, package );
1512c2c66affSColin Finck     msiobj_release( &si->hdr );
1513c2c66affSColin Finck     if (r != ERROR_SUCCESS)
1514c2c66affSColin Finck     {
1515c2c66affSColin Finck         WARN("failed to parse summary info %u\n", r);
1516c2c66affSColin Finck         msiobj_release( &package->hdr );
1517c2c66affSColin Finck         return r;
1518c2c66affSColin Finck     }
1519c2c66affSColin Finck     r = validate_package( package );
1520c2c66affSColin Finck     if (r != ERROR_SUCCESS)
1521c2c66affSColin Finck     {
1522c2c66affSColin Finck         msiobj_release( &package->hdr );
1523c2c66affSColin Finck         return r;
1524c2c66affSColin Finck     }
15250272139cSwinesync     msi_set_property( package->db, L"DATABASE", db->path, -1 );
1526c2c66affSColin Finck     set_installed_prop( package );
1527c2c66affSColin Finck     msi_set_context( package );
1528c2c66affSColin Finck 
1529da848361Swinesync     product_code = get_product_code( db );
1530da848361Swinesync     if (msi_locate_product( product_code, &context ) == ERROR_SUCCESS)
1531da848361Swinesync     {
1532da848361Swinesync         TRACE("product already registered\n");
15330272139cSwinesync         msi_set_property( package->db, L"ProductToBeRegistered", L"1", -1 );
1534da848361Swinesync     }
1535da848361Swinesync     msi_free(product_code);
1536da848361Swinesync 
1537c2c66affSColin Finck     while (1)
1538c2c66affSColin Finck     {
1539c2c66affSColin Finck         WCHAR patch_code[GUID_SIZE];
1540c2c66affSColin Finck         r = MsiEnumPatchesExW( package->ProductCode, NULL, package->Context,
1541c2c66affSColin Finck                                MSIPATCHSTATE_APPLIED, index, patch_code, NULL, NULL, NULL, NULL );
1542c2c66affSColin Finck         if (r != ERROR_SUCCESS)
1543c2c66affSColin Finck             break;
1544c2c66affSColin Finck 
1545c2c66affSColin Finck         TRACE("found registered patch %s\n", debugstr_w(patch_code));
1546c2c66affSColin Finck 
1547c2c66affSColin Finck         r = msi_apply_registered_patch( package, patch_code );
1548c2c66affSColin Finck         if (r != ERROR_SUCCESS)
1549c2c66affSColin Finck         {
1550c2c66affSColin Finck             ERR("registered patch failed to apply %u\n", r);
1551c2c66affSColin Finck             msiobj_release( &package->hdr );
1552c2c66affSColin Finck             return r;
1553c2c66affSColin Finck         }
1554c2c66affSColin Finck         index++;
1555c2c66affSColin Finck     }
1556c2c66affSColin Finck     if (index) msi_adjust_privilege_properties( package );
1557c2c66affSColin Finck 
1558c2c66affSColin Finck     r = msi_set_original_database_property( package->db, szPackage );
1559c2c66affSColin Finck     if (r != ERROR_SUCCESS)
1560c2c66affSColin Finck     {
1561c2c66affSColin Finck         msiobj_release( &package->hdr );
1562c2c66affSColin Finck         return r;
1563c2c66affSColin Finck     }
1564c2c66affSColin Finck     if (gszLogFile)
1565c2c66affSColin Finck         package->log_file = CreateFileW( gszLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
1566c2c66affSColin Finck                                          OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
156771bffdcdSAmine Khaldi 
1568e342f337Swinesync     if (!msi_init_assembly_caches( package ))
1569e342f337Swinesync     {
1570e342f337Swinesync         ERR("can't initialize assembly caches\n");
1571e342f337Swinesync         msiobj_release( &package->hdr );
1572e342f337Swinesync         return ERROR_FUNCTION_FAILED;
1573e342f337Swinesync     }
1574e342f337Swinesync 
157571bffdcdSAmine Khaldi     /* FIXME: when should these messages be sent? */
157671bffdcdSAmine Khaldi     data_row = MSI_CreateRecord(3);
157771bffdcdSAmine Khaldi     if (!data_row)
157871bffdcdSAmine Khaldi 	return ERROR_OUTOFMEMORY;
157971bffdcdSAmine Khaldi     MSI_RecordSetStringW(data_row, 0, NULL);
158071bffdcdSAmine Khaldi     MSI_RecordSetInteger(data_row, 1, 0);
158171bffdcdSAmine Khaldi     MSI_RecordSetInteger(data_row, 2, package->num_langids ? package->langids[0] : 0);
158271bffdcdSAmine Khaldi     MSI_RecordSetInteger(data_row, 3, msi_get_string_table_codepage(package->db->strings));
158371bffdcdSAmine Khaldi     MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_COMMONDATA, data_row);
158471bffdcdSAmine Khaldi 
158571bffdcdSAmine Khaldi     info_row = MSI_CreateRecord(0);
158671bffdcdSAmine Khaldi     if (!info_row)
158771bffdcdSAmine Khaldi     {
158871bffdcdSAmine Khaldi 	msiobj_release(&data_row->hdr);
158971bffdcdSAmine Khaldi 	return ERROR_OUTOFMEMORY;
159071bffdcdSAmine Khaldi     }
159171bffdcdSAmine Khaldi     info_template = msi_get_error_message(package->db, MSIERR_INFO_LOGGINGSTART);
159271bffdcdSAmine Khaldi     MSI_RecordSetStringW(info_row, 0, info_template);
159371bffdcdSAmine Khaldi     msi_free(info_template);
159471bffdcdSAmine Khaldi     MSI_ProcessMessage(package, INSTALLMESSAGE_INFO|MB_ICONHAND, info_row);
159571bffdcdSAmine Khaldi 
159671bffdcdSAmine Khaldi     MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, data_row);
159771bffdcdSAmine Khaldi 
159871bffdcdSAmine Khaldi     productname = msi_dup_property(package->db, INSTALLPROPERTY_PRODUCTNAMEW);
159971bffdcdSAmine Khaldi     MSI_RecordSetInteger(data_row, 1, 1);
160071bffdcdSAmine Khaldi     MSI_RecordSetStringW(data_row, 2, productname);
160171bffdcdSAmine Khaldi     MSI_RecordSetStringW(data_row, 3, NULL);
160271bffdcdSAmine Khaldi     MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, data_row);
160371bffdcdSAmine Khaldi 
160471bffdcdSAmine Khaldi     msi_free(productname);
160571bffdcdSAmine Khaldi     msiobj_release(&info_row->hdr);
160671bffdcdSAmine Khaldi     msiobj_release(&data_row->hdr);
160771bffdcdSAmine Khaldi 
1608c2c66affSColin Finck     *pPackage = package;
1609c2c66affSColin Finck     return ERROR_SUCCESS;
1610c2c66affSColin Finck }
1611c2c66affSColin Finck 
161202f995b2Swinesync UINT WINAPI MsiOpenPackageExW( const WCHAR *szPackage, DWORD dwOptions, MSIHANDLE *phPackage )
1613c2c66affSColin Finck {
1614c2c66affSColin Finck     MSIPACKAGE *package = NULL;
1615c2c66affSColin Finck     UINT ret;
1616c2c66affSColin Finck 
161702f995b2Swinesync     TRACE( "%s, %#lx, %p\n", debugstr_w(szPackage), dwOptions, phPackage );
1618c2c66affSColin Finck 
1619c2c66affSColin Finck     if( !szPackage || !phPackage )
1620c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
1621c2c66affSColin Finck 
1622c2c66affSColin Finck     if ( !*szPackage )
1623c2c66affSColin Finck     {
1624c2c66affSColin Finck         FIXME("Should create an empty database and package\n");
1625c2c66affSColin Finck         return ERROR_FUNCTION_FAILED;
1626c2c66affSColin Finck     }
1627c2c66affSColin Finck 
1628c2c66affSColin Finck     if( dwOptions )
162902f995b2Swinesync         FIXME( "dwOptions %#lx not supported\n", dwOptions );
1630c2c66affSColin Finck 
1631a2371385Swinesync     ret = MSI_OpenPackageW( szPackage, 0, &package );
1632c2c66affSColin Finck     if( ret == ERROR_SUCCESS )
1633c2c66affSColin Finck     {
1634c2c66affSColin Finck         *phPackage = alloc_msihandle( &package->hdr );
1635c2c66affSColin Finck         if (! *phPackage)
1636c2c66affSColin Finck             ret = ERROR_NOT_ENOUGH_MEMORY;
1637c2c66affSColin Finck         msiobj_release( &package->hdr );
1638c2c66affSColin Finck     }
163971bffdcdSAmine Khaldi     else
164071bffdcdSAmine Khaldi         MSI_ProcessMessage(NULL, INSTALLMESSAGE_TERMINATE, 0);
1641c2c66affSColin Finck 
1642c2c66affSColin Finck     return ret;
1643c2c66affSColin Finck }
1644c2c66affSColin Finck 
1645c2c66affSColin Finck UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
1646c2c66affSColin Finck {
1647c2c66affSColin Finck     return MsiOpenPackageExW( szPackage, 0, phPackage );
1648c2c66affSColin Finck }
1649c2c66affSColin Finck 
1650c2c66affSColin Finck UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
1651c2c66affSColin Finck {
1652c2c66affSColin Finck     LPWSTR szwPack = NULL;
1653c2c66affSColin Finck     UINT ret;
1654c2c66affSColin Finck 
1655c2c66affSColin Finck     if( szPackage )
1656c2c66affSColin Finck     {
1657c2c66affSColin Finck         szwPack = strdupAtoW( szPackage );
1658c2c66affSColin Finck         if( !szwPack )
1659c2c66affSColin Finck             return ERROR_OUTOFMEMORY;
1660c2c66affSColin Finck     }
1661c2c66affSColin Finck 
1662c2c66affSColin Finck     ret = MsiOpenPackageExW( szwPack, dwOptions, phPackage );
1663c2c66affSColin Finck 
1664c2c66affSColin Finck     msi_free( szwPack );
1665c2c66affSColin Finck 
1666c2c66affSColin Finck     return ret;
1667c2c66affSColin Finck }
1668c2c66affSColin Finck 
1669c2c66affSColin Finck UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
1670c2c66affSColin Finck {
1671c2c66affSColin Finck     return MsiOpenPackageExA( szPackage, 0, phPackage );
1672c2c66affSColin Finck }
1673c2c66affSColin Finck 
1674c2c66affSColin Finck MSIHANDLE WINAPI MsiGetActiveDatabase( MSIHANDLE hInstall )
1675c2c66affSColin Finck {
1676c2c66affSColin Finck     MSIPACKAGE *package;
1677c2c66affSColin Finck     MSIHANDLE handle = 0;
1678b74b77aaSwinesync     MSIHANDLE remote;
1679c2c66affSColin Finck 
168002f995b2Swinesync     TRACE( "%lu\n", hInstall );
1681c2c66affSColin Finck 
1682c2c66affSColin Finck     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
1683c2c66affSColin Finck     if( package)
1684c2c66affSColin Finck     {
1685c2c66affSColin Finck         handle = alloc_msihandle( &package->db->hdr );
1686c2c66affSColin Finck         msiobj_release( &package->hdr );
1687c2c66affSColin Finck     }
1688b74b77aaSwinesync     else if ((remote = msi_get_remote(hInstall)))
1689c2c66affSColin Finck     {
16902a9ae858Swinesync         __TRY
16912a9ae858Swinesync         {
1692bf1ca658Swinesync             handle = remote_GetActiveDatabase(remote);
16937cc54a4fSwinesync             handle = alloc_msi_remote_handle(handle);
1694c2c66affSColin Finck         }
16952a9ae858Swinesync         __EXCEPT(rpc_filter)
16962a9ae858Swinesync         {
16972a9ae858Swinesync             handle = 0;
16982a9ae858Swinesync         }
16992a9ae858Swinesync         __ENDTRY
17002a9ae858Swinesync     }
1701c2c66affSColin Finck 
1702c2c66affSColin Finck     return handle;
1703c2c66affSColin Finck }
1704c2c66affSColin Finck 
170571bffdcdSAmine Khaldi static INT internal_ui_handler(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record, LPCWSTR message)
1706c2c66affSColin Finck {
170771bffdcdSAmine Khaldi     if (!package || (package->ui_level & INSTALLUILEVEL_MASK) == INSTALLUILEVEL_NONE)
170871bffdcdSAmine Khaldi         return 0;
170971bffdcdSAmine Khaldi 
171071bffdcdSAmine Khaldi     /* todo: check if message needs additional styles (topmost/foreground/modality?) */
171171bffdcdSAmine Khaldi 
171271bffdcdSAmine Khaldi     switch (eMessageType & 0xff000000)
171371bffdcdSAmine Khaldi     {
171471bffdcdSAmine Khaldi     case INSTALLMESSAGE_FATALEXIT:
171571bffdcdSAmine Khaldi     case INSTALLMESSAGE_ERROR:
171671bffdcdSAmine Khaldi     case INSTALLMESSAGE_OUTOFDISKSPACE:
171771bffdcdSAmine Khaldi         if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0;
171871bffdcdSAmine Khaldi         if (!(eMessageType & MB_ICONMASK))
171971bffdcdSAmine Khaldi             eMessageType |= MB_ICONEXCLAMATION;
17200272139cSwinesync         return MessageBoxW(gUIhwnd, message, L"Windows Installer", eMessageType & 0x00ffffff);
172171bffdcdSAmine Khaldi     case INSTALLMESSAGE_WARNING:
172271bffdcdSAmine Khaldi         if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0;
172371bffdcdSAmine Khaldi         if (!(eMessageType & MB_ICONMASK))
172471bffdcdSAmine Khaldi             eMessageType |= MB_ICONASTERISK;
17250272139cSwinesync         return MessageBoxW(gUIhwnd, message, L"Windows Installer", eMessageType & 0x00ffffff);
172671bffdcdSAmine Khaldi     case INSTALLMESSAGE_USER:
172771bffdcdSAmine Khaldi         if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0;
172871bffdcdSAmine Khaldi         if (!(eMessageType & MB_ICONMASK))
172971bffdcdSAmine Khaldi             eMessageType |= MB_USERICON;
17300272139cSwinesync         return MessageBoxW(gUIhwnd, message, L"Windows Installer", eMessageType & 0x00ffffff);
173171bffdcdSAmine Khaldi     case INSTALLMESSAGE_INFO:
173271bffdcdSAmine Khaldi     case INSTALLMESSAGE_INITIALIZE:
173371bffdcdSAmine Khaldi     case INSTALLMESSAGE_TERMINATE:
1734f8b992f2SAmine Khaldi     case INSTALLMESSAGE_INSTALLSTART:
1735f8b992f2SAmine Khaldi     case INSTALLMESSAGE_INSTALLEND:
173671bffdcdSAmine Khaldi         return 0;
173771bffdcdSAmine Khaldi     case INSTALLMESSAGE_SHOWDIALOG:
173871bffdcdSAmine Khaldi     {
173971bffdcdSAmine Khaldi         LPWSTR dialog = msi_dup_record_field(record, 0);
174071bffdcdSAmine Khaldi         INT rc = ACTION_DialogBox(package, dialog);
174171bffdcdSAmine Khaldi         msi_free(dialog);
174271bffdcdSAmine Khaldi         return rc;
174371bffdcdSAmine Khaldi     }
174471bffdcdSAmine Khaldi     case INSTALLMESSAGE_ACTIONSTART:
174571bffdcdSAmine Khaldi     {
174671bffdcdSAmine Khaldi         LPWSTR deformatted;
174771bffdcdSAmine Khaldi         MSIRECORD *uirow = MSI_CreateRecord(1);
174871bffdcdSAmine Khaldi         if (!uirow) return -1;
174971bffdcdSAmine Khaldi         deformat_string(package, MSI_RecordGetString(record, 2), &deformatted);
175071bffdcdSAmine Khaldi         MSI_RecordSetStringW(uirow, 1, deformatted);
17510272139cSwinesync         msi_event_fire(package, L"ActionText", uirow);
175271bffdcdSAmine Khaldi 
175371bffdcdSAmine Khaldi         msi_free(deformatted);
175471bffdcdSAmine Khaldi         msiobj_release(&uirow->hdr);
175571bffdcdSAmine Khaldi         return 1;
175671bffdcdSAmine Khaldi     }
175771bffdcdSAmine Khaldi     case INSTALLMESSAGE_ACTIONDATA:
175871bffdcdSAmine Khaldi     {
175971bffdcdSAmine Khaldi         MSIRECORD *uirow = MSI_CreateRecord(1);
176071bffdcdSAmine Khaldi         if (!uirow) return -1;
176171bffdcdSAmine Khaldi         MSI_RecordSetStringW(uirow, 1, message);
17620272139cSwinesync         msi_event_fire(package, L"ActionData", uirow);
176371bffdcdSAmine Khaldi         msiobj_release(&uirow->hdr);
176471bffdcdSAmine Khaldi 
176571bffdcdSAmine Khaldi         if (package->action_progress_increment)
176671bffdcdSAmine Khaldi         {
176771bffdcdSAmine Khaldi             uirow = MSI_CreateRecord(2);
176871bffdcdSAmine Khaldi             if (!uirow) return -1;
176971bffdcdSAmine Khaldi             MSI_RecordSetInteger(uirow, 1, 2);
177071bffdcdSAmine Khaldi             MSI_RecordSetInteger(uirow, 2, package->action_progress_increment);
17710272139cSwinesync             msi_event_fire(package, L"SetProgress", uirow);
177271bffdcdSAmine Khaldi             msiobj_release(&uirow->hdr);
177371bffdcdSAmine Khaldi         }
177471bffdcdSAmine Khaldi         return 1;
177571bffdcdSAmine Khaldi     }
177671bffdcdSAmine Khaldi     case INSTALLMESSAGE_PROGRESS:
17770272139cSwinesync         msi_event_fire(package, L"SetProgress", record);
177871bffdcdSAmine Khaldi         return 1;
177971bffdcdSAmine Khaldi     case INSTALLMESSAGE_COMMONDATA:
178071bffdcdSAmine Khaldi         switch (MSI_RecordGetInteger(record, 1))
178171bffdcdSAmine Khaldi         {
178271bffdcdSAmine Khaldi         case 0:
178371bffdcdSAmine Khaldi         case 1:
178471bffdcdSAmine Khaldi             /* do nothing */
178571bffdcdSAmine Khaldi             return 0;
178671bffdcdSAmine Khaldi         default:
178771bffdcdSAmine Khaldi             /* fall through */
178871bffdcdSAmine Khaldi             ;
178971bffdcdSAmine Khaldi         }
179071bffdcdSAmine Khaldi     default:
179171bffdcdSAmine Khaldi         FIXME("internal UI not implemented for message 0x%08x (UI level = %x)\n", eMessageType, package->ui_level);
179271bffdcdSAmine Khaldi         return 0;
179371bffdcdSAmine Khaldi     }
179471bffdcdSAmine Khaldi }
179571bffdcdSAmine Khaldi 
179671bffdcdSAmine Khaldi static const struct
179771bffdcdSAmine Khaldi {
179871bffdcdSAmine Khaldi     int id;
179971bffdcdSAmine Khaldi     const WCHAR *text;
180071bffdcdSAmine Khaldi }
180171bffdcdSAmine Khaldi internal_errors[] =
180271bffdcdSAmine Khaldi {
18030272139cSwinesync     {2726, L"DEBUG: Error [1]:  Action not found: [2]"},
180471bffdcdSAmine Khaldi     {0}
180571bffdcdSAmine Khaldi };
180671bffdcdSAmine Khaldi 
180771bffdcdSAmine Khaldi static LPCWSTR get_internal_error_message(int error)
180871bffdcdSAmine Khaldi {
180971bffdcdSAmine Khaldi     int i = 0;
181071bffdcdSAmine Khaldi 
181171bffdcdSAmine Khaldi     while (internal_errors[i].id != 0)
181271bffdcdSAmine Khaldi     {
181371bffdcdSAmine Khaldi         if (internal_errors[i].id == error)
181471bffdcdSAmine Khaldi             return internal_errors[i].text;
181571bffdcdSAmine Khaldi         i++;
181671bffdcdSAmine Khaldi     }
181771bffdcdSAmine Khaldi 
181871bffdcdSAmine Khaldi     FIXME("missing error message %d\n", error);
181971bffdcdSAmine Khaldi     return NULL;
182071bffdcdSAmine Khaldi }
182171bffdcdSAmine Khaldi 
182271bffdcdSAmine Khaldi /* Returned string must be freed */
182371bffdcdSAmine Khaldi LPWSTR msi_get_error_message(MSIDATABASE *db, int error)
182471bffdcdSAmine Khaldi {
182571bffdcdSAmine Khaldi     MSIRECORD *record;
182671bffdcdSAmine Khaldi     LPWSTR ret = NULL;
182771bffdcdSAmine Khaldi 
18280272139cSwinesync     if ((record = MSI_QueryGetRecord(db, L"SELECT `Message` FROM `Error` WHERE `Error` = %d", error)))
182971bffdcdSAmine Khaldi     {
183071bffdcdSAmine Khaldi         ret = msi_dup_record_field(record, 1);
183171bffdcdSAmine Khaldi         msiobj_release(&record->hdr);
183271bffdcdSAmine Khaldi     }
183371bffdcdSAmine Khaldi     else if (error < 2000)
183471bffdcdSAmine Khaldi     {
183571bffdcdSAmine Khaldi         int len = LoadStringW(msi_hInstance, IDS_ERROR_BASE + error, (LPWSTR) &ret, 0);
183671bffdcdSAmine Khaldi         if (len)
183771bffdcdSAmine Khaldi         {
183871bffdcdSAmine Khaldi             ret = msi_alloc((len + 1) * sizeof(WCHAR));
183971bffdcdSAmine Khaldi             LoadStringW(msi_hInstance, IDS_ERROR_BASE + error, ret, len + 1);
184071bffdcdSAmine Khaldi         }
184171bffdcdSAmine Khaldi         else
184271bffdcdSAmine Khaldi             ret = NULL;
184371bffdcdSAmine Khaldi     }
184471bffdcdSAmine Khaldi 
184571bffdcdSAmine Khaldi     return ret;
184671bffdcdSAmine Khaldi }
184771bffdcdSAmine Khaldi 
184871bffdcdSAmine Khaldi INT MSI_ProcessMessageVerbatim(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record)
184971bffdcdSAmine Khaldi {
185071bffdcdSAmine Khaldi     LPWSTR message = {0};
1851f8b992f2SAmine Khaldi     DWORD len;
1852f8b992f2SAmine Khaldi     DWORD log_type = 1 << (eMessageType >> 24);
185371bffdcdSAmine Khaldi     UINT res;
1854c2c66affSColin Finck     INT rc = 0;
1855c2c66affSColin Finck     char *msg;
1856c2c66affSColin Finck 
1857c2c66affSColin Finck     TRACE("%x\n", eMessageType);
185871bffdcdSAmine Khaldi     if (TRACE_ON(msi)) dump_record(record);
1859c2c66affSColin Finck 
186071bffdcdSAmine Khaldi     if (!package || !record)
186171bffdcdSAmine Khaldi         message = NULL;
186271bffdcdSAmine Khaldi     else {
186371bffdcdSAmine Khaldi         res = MSI_FormatRecordW(package, record, message, &len);
186471bffdcdSAmine Khaldi         if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
186571bffdcdSAmine Khaldi             return res;
186671bffdcdSAmine Khaldi         len++;
1867c2c66affSColin Finck         message = msi_alloc(len * sizeof(WCHAR));
186871bffdcdSAmine Khaldi         if (!message) return ERROR_OUTOFMEMORY;
186971bffdcdSAmine Khaldi         MSI_FormatRecordW(package, record, message, &len);
1870c2c66affSColin Finck     }
1871c2c66affSColin Finck 
1872026a2db6Swinesync     /* convert it to ANSI */
1873c2c66affSColin Finck     len = WideCharToMultiByte( CP_ACP, 0, message, -1, NULL, 0, NULL, NULL );
1874c2c66affSColin Finck     msg = msi_alloc( len );
1875c2c66affSColin Finck     WideCharToMultiByte( CP_ACP, 0, message, -1, msg, len, NULL, NULL );
1876c2c66affSColin Finck 
187771bffdcdSAmine Khaldi     if (gUIHandlerRecord && (gUIFilterRecord & log_type))
1878c2c66affSColin Finck     {
187971bffdcdSAmine Khaldi         MSIHANDLE rec = alloc_msihandle(&record->hdr);
188002f995b2Swinesync         TRACE( "calling UI handler %p(pvContext = %p, iMessageType = %#x, hRecord = %lu)\n",
188171bffdcdSAmine Khaldi                gUIHandlerRecord, gUIContextRecord, eMessageType, rec );
188271bffdcdSAmine Khaldi         rc = gUIHandlerRecord( gUIContextRecord, eMessageType, rec );
1883c2c66affSColin Finck         MsiCloseHandle( rec );
1884c2c66affSColin Finck     }
188571bffdcdSAmine Khaldi     if (!rc && gUIHandlerW && (gUIFilter & log_type))
188671bffdcdSAmine Khaldi     {
188702f995b2Swinesync         TRACE( "calling UI handler %p(pvContext = %p, iMessageType = %#x, szMessage = %s)\n",
188871bffdcdSAmine Khaldi                gUIHandlerW, gUIContext, eMessageType, debugstr_w(message) );
188971bffdcdSAmine Khaldi         rc = gUIHandlerW( gUIContext, eMessageType, message );
189071bffdcdSAmine Khaldi     }
189171bffdcdSAmine Khaldi     else if (!rc && gUIHandlerA && (gUIFilter & log_type))
189271bffdcdSAmine Khaldi     {
189302f995b2Swinesync         TRACE( "calling UI handler %p(pvContext = %p, iMessageType = %#x, szMessage = %s)\n",
189471bffdcdSAmine Khaldi                gUIHandlerA, gUIContext, eMessageType, debugstr_a(msg) );
189571bffdcdSAmine Khaldi         rc = gUIHandlerA( gUIContext, eMessageType, msg );
189671bffdcdSAmine Khaldi     }
1897c2c66affSColin Finck 
189871bffdcdSAmine Khaldi     if (!rc)
189971bffdcdSAmine Khaldi         rc = internal_ui_handler(package, eMessageType, record, message);
190071bffdcdSAmine Khaldi 
190171bffdcdSAmine Khaldi     if (!rc && package && package->log_file != INVALID_HANDLE_VALUE &&
1902c2c66affSColin Finck         (eMessageType & 0xff000000) != INSTALLMESSAGE_PROGRESS)
1903c2c66affSColin Finck     {
1904c2c66affSColin Finck         DWORD written;
1905c2c66affSColin Finck         WriteFile( package->log_file, msg, len - 1, &written, NULL );
1906c2c66affSColin Finck         WriteFile( package->log_file, "\n", 1, &written, NULL );
1907c2c66affSColin Finck     }
1908c2c66affSColin Finck     msi_free( msg );
1909c2c66affSColin Finck     msi_free( message );
1910c2c66affSColin Finck 
191171bffdcdSAmine Khaldi     return rc;
191271bffdcdSAmine Khaldi }
191371bffdcdSAmine Khaldi 
191471bffdcdSAmine Khaldi INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record )
191571bffdcdSAmine Khaldi {
1916c2c66affSColin Finck     switch (eMessageType & 0xff000000)
1917c2c66affSColin Finck     {
191871bffdcdSAmine Khaldi     case INSTALLMESSAGE_FATALEXIT:
191971bffdcdSAmine Khaldi     case INSTALLMESSAGE_ERROR:
192071bffdcdSAmine Khaldi     case INSTALLMESSAGE_WARNING:
192171bffdcdSAmine Khaldi     case INSTALLMESSAGE_USER:
192271bffdcdSAmine Khaldi     case INSTALLMESSAGE_INFO:
192371bffdcdSAmine Khaldi     case INSTALLMESSAGE_OUTOFDISKSPACE:
192471bffdcdSAmine Khaldi         if (MSI_RecordGetInteger(record, 1) != MSI_NULL_INTEGER)
1925c2c66affSColin Finck         {
192671bffdcdSAmine Khaldi             /* error message */
192771bffdcdSAmine Khaldi 
192871bffdcdSAmine Khaldi             LPWSTR template;
192971bffdcdSAmine Khaldi             LPWSTR template_rec = NULL, template_prefix = NULL;
193071bffdcdSAmine Khaldi             int error = MSI_RecordGetInteger(record, 1);
193171bffdcdSAmine Khaldi 
193271bffdcdSAmine Khaldi             if (MSI_RecordIsNull(record, 0))
193371bffdcdSAmine Khaldi             {
193471bffdcdSAmine Khaldi                 if (error >= 32)
193571bffdcdSAmine Khaldi                 {
193671bffdcdSAmine Khaldi                     template_rec = msi_get_error_message(package->db, error);
193771bffdcdSAmine Khaldi 
193871bffdcdSAmine Khaldi                     if (!template_rec && error >= 2000)
193971bffdcdSAmine Khaldi                     {
194071bffdcdSAmine Khaldi                         /* internal error, not localized */
194171bffdcdSAmine Khaldi                         if ((template_rec = (LPWSTR) get_internal_error_message(error)))
194271bffdcdSAmine Khaldi                         {
194371bffdcdSAmine Khaldi                             MSI_RecordSetStringW(record, 0, template_rec);
194471bffdcdSAmine Khaldi                             MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_INFO, record);
194571bffdcdSAmine Khaldi                         }
194671bffdcdSAmine Khaldi                         template_rec = msi_get_error_message(package->db, MSIERR_INSTALLERROR);
194771bffdcdSAmine Khaldi                         MSI_RecordSetStringW(record, 0, template_rec);
194871bffdcdSAmine Khaldi                         MSI_ProcessMessageVerbatim(package, eMessageType, record);
194971bffdcdSAmine Khaldi                         msi_free(template_rec);
195071bffdcdSAmine Khaldi                         return 0;
195171bffdcdSAmine Khaldi                     }
195271bffdcdSAmine Khaldi                 }
195371bffdcdSAmine Khaldi             }
195471bffdcdSAmine Khaldi             else
195571bffdcdSAmine Khaldi                 template_rec = msi_dup_record_field(record, 0);
195671bffdcdSAmine Khaldi 
195771bffdcdSAmine Khaldi             template_prefix = msi_get_error_message(package->db, eMessageType >> 24);
19580272139cSwinesync             if (!template_prefix) template_prefix = strdupW(L"");
195971bffdcdSAmine Khaldi 
196071bffdcdSAmine Khaldi             if (!template_rec)
196171bffdcdSAmine Khaldi             {
196271bffdcdSAmine Khaldi                 /* always returns 0 */
196371bffdcdSAmine Khaldi                 MSI_RecordSetStringW(record, 0, template_prefix);
196471bffdcdSAmine Khaldi                 MSI_ProcessMessageVerbatim(package, eMessageType, record);
196571bffdcdSAmine Khaldi                 msi_free(template_prefix);
196671bffdcdSAmine Khaldi                 return 0;
196771bffdcdSAmine Khaldi             }
196871bffdcdSAmine Khaldi 
1969958f1addSwinesync             template = msi_alloc((lstrlenW(template_rec) + lstrlenW(template_prefix) + 1) * sizeof(WCHAR));
197071bffdcdSAmine Khaldi             if (!template) return ERROR_OUTOFMEMORY;
197171bffdcdSAmine Khaldi 
1972958f1addSwinesync             lstrcpyW(template, template_prefix);
1973958f1addSwinesync             lstrcatW(template, template_rec);
197471bffdcdSAmine Khaldi             MSI_RecordSetStringW(record, 0, template);
197571bffdcdSAmine Khaldi 
197671bffdcdSAmine Khaldi             msi_free(template_prefix);
197771bffdcdSAmine Khaldi             msi_free(template_rec);
197871bffdcdSAmine Khaldi             msi_free(template);
1979c2c66affSColin Finck         }
1980c2c66affSColin Finck         break;
1981c2c66affSColin Finck     case INSTALLMESSAGE_ACTIONSTART:
198271bffdcdSAmine Khaldi     {
198371bffdcdSAmine Khaldi         WCHAR *template = msi_get_error_message(package->db, MSIERR_ACTIONSTART);
198471bffdcdSAmine Khaldi         MSI_RecordSetStringW(record, 0, template);
198571bffdcdSAmine Khaldi         msi_free(template);
1986c2c66affSColin Finck 
198771bffdcdSAmine Khaldi         msi_free(package->LastAction);
198871bffdcdSAmine Khaldi         msi_free(package->LastActionTemplate);
198971bffdcdSAmine Khaldi         package->LastAction = msi_dup_record_field(record, 1);
19900272139cSwinesync         if (!package->LastAction) package->LastAction = strdupW(L"");
199171bffdcdSAmine Khaldi         package->LastActionTemplate = msi_dup_record_field(record, 3);
1992c2c66affSColin Finck         break;
199371bffdcdSAmine Khaldi     }
199471bffdcdSAmine Khaldi     case INSTALLMESSAGE_ACTIONDATA:
199571bffdcdSAmine Khaldi         if (package->LastAction && package->LastActionTemplate)
199671bffdcdSAmine Khaldi         {
1997958f1addSwinesync             size_t len = lstrlenW(package->LastAction) + lstrlenW(package->LastActionTemplate) + 7;
1998958f1addSwinesync             WCHAR *template = msi_alloc(len * sizeof(WCHAR));
199971bffdcdSAmine Khaldi             if (!template) return ERROR_OUTOFMEMORY;
20000272139cSwinesync             swprintf(template, len, L"{{%s: }}%s", package->LastAction, package->LastActionTemplate);
200171bffdcdSAmine Khaldi             MSI_RecordSetStringW(record, 0, template);
200271bffdcdSAmine Khaldi             msi_free(template);
200371bffdcdSAmine Khaldi         }
200471bffdcdSAmine Khaldi         break;
200571bffdcdSAmine Khaldi     case INSTALLMESSAGE_COMMONDATA:
200671bffdcdSAmine Khaldi     {
200771bffdcdSAmine Khaldi         WCHAR *template = msi_get_error_message(package->db, MSIERR_COMMONDATA);
200871bffdcdSAmine Khaldi         MSI_RecordSetStringW(record, 0, template);
200971bffdcdSAmine Khaldi         msi_free(template);
201071bffdcdSAmine Khaldi     }
2011c2c66affSColin Finck     break;
2012c2c66affSColin Finck     }
2013c2c66affSColin Finck 
201471bffdcdSAmine Khaldi     return MSI_ProcessMessageVerbatim(package, eMessageType, record);
2015c2c66affSColin Finck }
2016c2c66affSColin Finck 
2017c2c66affSColin Finck INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
2018c2c66affSColin Finck                               MSIHANDLE hRecord)
2019c2c66affSColin Finck {
2020c2c66affSColin Finck     UINT ret = ERROR_INVALID_HANDLE;
2021c2c66affSColin Finck     MSIPACKAGE *package = NULL;
2022c2c66affSColin Finck     MSIRECORD *record = NULL;
2023c2c66affSColin Finck 
202471bffdcdSAmine Khaldi     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INITIALIZE ||
202571bffdcdSAmine Khaldi         (eMessageType & 0xff000000) == INSTALLMESSAGE_TERMINATE)
202671bffdcdSAmine Khaldi         return -1;
202771bffdcdSAmine Khaldi 
202871bffdcdSAmine Khaldi     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA &&
202971bffdcdSAmine Khaldi         MsiRecordGetInteger(hRecord, 1) != 2)
203071bffdcdSAmine Khaldi         return -1;
203171bffdcdSAmine Khaldi 
20322e19edd6Swinesync     record = msihandle2msiinfo(hRecord, MSIHANDLETYPE_RECORD);
20332e19edd6Swinesync     if (!record)
20342e19edd6Swinesync         return ERROR_INVALID_HANDLE;
20352e19edd6Swinesync 
2036c2c66affSColin Finck     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
2037c2c66affSColin Finck     if( !package )
2038c2c66affSColin Finck     {
2039b74b77aaSwinesync         MSIHANDLE remote;
2040c2c66affSColin Finck 
2041b74b77aaSwinesync         if (!(remote = msi_get_remote(hInstall)))
2042c2c66affSColin Finck             return ERROR_INVALID_HANDLE;
2043c2c66affSColin Finck 
20442a9ae858Swinesync         __TRY
20452a9ae858Swinesync         {
20462e19edd6Swinesync             ret = remote_ProcessMessage(remote, eMessageType, (struct wire_record *)&record->count);
20472a9ae858Swinesync         }
20482a9ae858Swinesync         __EXCEPT(rpc_filter)
20492a9ae858Swinesync         {
20502a9ae858Swinesync             ret = GetExceptionCode();
20512a9ae858Swinesync         }
20522a9ae858Swinesync         __ENDTRY
2053c2c66affSColin Finck 
20542e19edd6Swinesync         msiobj_release(&record->hdr);
20552e19edd6Swinesync         return ret;
2056c2c66affSColin Finck     }
2057c2c66affSColin Finck 
2058c2c66affSColin Finck     ret = MSI_ProcessMessage( package, eMessageType, record );
2059c2c66affSColin Finck 
2060eab017d1Swinesync     msiobj_release( &record->hdr );
2061c2c66affSColin Finck     msiobj_release( &package->hdr );
2062c2c66affSColin Finck     return ret;
2063c2c66affSColin Finck }
2064c2c66affSColin Finck 
2065c2c66affSColin Finck /* property code */
2066c2c66affSColin Finck 
2067c2c66affSColin Finck UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue )
2068c2c66affSColin Finck {
2069c2c66affSColin Finck     LPWSTR szwName = NULL, szwValue = NULL;
2070c2c66affSColin Finck     UINT r = ERROR_OUTOFMEMORY;
2071c2c66affSColin Finck 
2072c2c66affSColin Finck     szwName = strdupAtoW( szName );
2073c2c66affSColin Finck     if( szName && !szwName )
2074c2c66affSColin Finck         goto end;
2075c2c66affSColin Finck 
2076c2c66affSColin Finck     szwValue = strdupAtoW( szValue );
2077c2c66affSColin Finck     if( szValue && !szwValue )
2078c2c66affSColin Finck         goto end;
2079c2c66affSColin Finck 
2080c2c66affSColin Finck     r = MsiSetPropertyW( hInstall, szwName, szwValue);
2081c2c66affSColin Finck 
2082c2c66affSColin Finck end:
2083c2c66affSColin Finck     msi_free( szwName );
2084c2c66affSColin Finck     msi_free( szwValue );
2085c2c66affSColin Finck 
2086c2c66affSColin Finck     return r;
2087c2c66affSColin Finck }
2088c2c66affSColin Finck 
20890922e524Swinesync void msi_reset_source_folders( MSIPACKAGE *package )
2090c2c66affSColin Finck {
2091c2c66affSColin Finck     MSIFOLDER *folder;
2092c2c66affSColin Finck 
2093c2c66affSColin Finck     LIST_FOR_EACH_ENTRY( folder, &package->folders, MSIFOLDER, entry )
2094c2c66affSColin Finck     {
2095c2c66affSColin Finck         msi_free( folder->ResolvedSource );
2096c2c66affSColin Finck         folder->ResolvedSource = NULL;
2097c2c66affSColin Finck     }
2098c2c66affSColin Finck }
2099c2c66affSColin Finck 
2100c2c66affSColin Finck UINT msi_set_property( MSIDATABASE *db, const WCHAR *name, const WCHAR *value, int len )
2101c2c66affSColin Finck {
2102c2c66affSColin Finck     MSIQUERY *view;
2103c2c66affSColin Finck     MSIRECORD *row = NULL;
2104c2c66affSColin Finck     DWORD sz = 0;
2105c2c66affSColin Finck     WCHAR query[1024];
2106c2c66affSColin Finck     UINT rc;
2107c2c66affSColin Finck 
2108c2c66affSColin Finck     TRACE("%p %s %s %d\n", db, debugstr_w(name), debugstr_wn(value, len), len);
2109c2c66affSColin Finck 
2110c2c66affSColin Finck     if (!name)
2111c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
2112c2c66affSColin Finck 
2113c2c66affSColin Finck     /* this one is weird... */
2114c2c66affSColin Finck     if (!name[0])
2115c2c66affSColin Finck         return value ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS;
2116c2c66affSColin Finck 
2117958f1addSwinesync     if (value && len < 0) len = lstrlenW( value );
2118c2c66affSColin Finck 
2119c2c66affSColin Finck     rc = msi_get_property( db, name, 0, &sz );
2120c2c66affSColin Finck     if (!value || (!*value && !len))
2121c2c66affSColin Finck     {
21220272139cSwinesync         swprintf( query, ARRAY_SIZE(query), L"DELETE FROM `_Property` WHERE `_Property` = '%s'", name );
2123c2c66affSColin Finck     }
2124c2c66affSColin Finck     else if (rc == ERROR_MORE_DATA || rc == ERROR_SUCCESS)
2125c2c66affSColin Finck     {
21260272139cSwinesync         swprintf( query, ARRAY_SIZE(query), L"UPDATE `_Property` SET `Value` = ? WHERE `_Property` = '%s'", name );
2127c2c66affSColin Finck         row = MSI_CreateRecord(1);
2128c2c66affSColin Finck         msi_record_set_string( row, 1, value, len );
2129c2c66affSColin Finck     }
2130c2c66affSColin Finck     else
2131c2c66affSColin Finck     {
21320272139cSwinesync         lstrcpyW( query, L"INSERT INTO `_Property` (`_Property`,`Value`) VALUES (?,?)" );
2133c2c66affSColin Finck         row = MSI_CreateRecord(2);
2134c2c66affSColin Finck         msi_record_set_string( row, 1, name, -1 );
2135c2c66affSColin Finck         msi_record_set_string( row, 2, value, len );
2136c2c66affSColin Finck     }
2137c2c66affSColin Finck 
2138c2c66affSColin Finck     rc = MSI_DatabaseOpenViewW(db, query, &view);
2139c2c66affSColin Finck     if (rc == ERROR_SUCCESS)
2140c2c66affSColin Finck     {
2141c2c66affSColin Finck         rc = MSI_ViewExecute(view, row);
2142c2c66affSColin Finck         MSI_ViewClose(view);
2143c2c66affSColin Finck         msiobj_release(&view->hdr);
2144c2c66affSColin Finck     }
2145c2c66affSColin Finck     if (row) msiobj_release(&row->hdr);
2146c2c66affSColin Finck     return rc;
2147c2c66affSColin Finck }
2148c2c66affSColin Finck 
2149c2c66affSColin Finck UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue)
2150c2c66affSColin Finck {
2151c2c66affSColin Finck     MSIPACKAGE *package;
2152c2c66affSColin Finck     UINT ret;
2153c2c66affSColin Finck 
2154c2c66affSColin Finck     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
2155c2c66affSColin Finck     if( !package )
2156c2c66affSColin Finck     {
2157b74b77aaSwinesync         MSIHANDLE remote;
2158c2c66affSColin Finck 
2159b74b77aaSwinesync         if (!(remote = msi_get_remote(hInstall)))
2160c2c66affSColin Finck             return ERROR_INVALID_HANDLE;
2161c2c66affSColin Finck 
21622a9ae858Swinesync         __TRY
21632a9ae858Swinesync         {
21642a9ae858Swinesync             ret = remote_SetProperty(remote, szName, szValue);
21652a9ae858Swinesync         }
21662a9ae858Swinesync         __EXCEPT(rpc_filter)
21672a9ae858Swinesync         {
21682a9ae858Swinesync             ret = GetExceptionCode();
21692a9ae858Swinesync         }
21702a9ae858Swinesync         __ENDTRY
21712a9ae858Swinesync 
21722a9ae858Swinesync         return ret;
2173c2c66affSColin Finck     }
2174c2c66affSColin Finck 
2175c2c66affSColin Finck     ret = msi_set_property( package->db, szName, szValue, -1 );
21760272139cSwinesync     if (ret == ERROR_SUCCESS && !wcscmp( szName, L"SourceDir" ))
21770922e524Swinesync         msi_reset_source_folders( package );
2178c2c66affSColin Finck 
2179c2c66affSColin Finck     msiobj_release( &package->hdr );
2180c2c66affSColin Finck     return ret;
2181c2c66affSColin Finck }
2182c2c66affSColin Finck 
2183c2c66affSColin Finck static MSIRECORD *msi_get_property_row( MSIDATABASE *db, LPCWSTR name )
2184c2c66affSColin Finck {
2185c2c66affSColin Finck     MSIRECORD *rec, *row = NULL;
2186c2c66affSColin Finck     MSIQUERY *view;
2187c2c66affSColin Finck     UINT r;
218871bffdcdSAmine Khaldi     WCHAR *buffer;
218971bffdcdSAmine Khaldi     int length;
219071bffdcdSAmine Khaldi 
2191c2c66affSColin Finck     if (!name || !*name)
2192c2c66affSColin Finck         return NULL;
2193c2c66affSColin Finck 
21940272139cSwinesync     if (!wcscmp(name, L"Date"))
219571bffdcdSAmine Khaldi     {
219671bffdcdSAmine Khaldi         length = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, NULL, 0);
219771bffdcdSAmine Khaldi         if (!length)
219871bffdcdSAmine Khaldi             return NULL;
219971bffdcdSAmine Khaldi         buffer = msi_alloc(length * sizeof(WCHAR));
2200fec16ab0SAmine Khaldi         GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, buffer, length);
220171bffdcdSAmine Khaldi 
220271bffdcdSAmine Khaldi         row = MSI_CreateRecord(1);
220371bffdcdSAmine Khaldi         if (!row)
2204f8b992f2SAmine Khaldi         {
2205f8b992f2SAmine Khaldi             msi_free(buffer);
220671bffdcdSAmine Khaldi             return NULL;
2207f8b992f2SAmine Khaldi         }
220871bffdcdSAmine Khaldi         MSI_RecordSetStringW(row, 1, buffer);
220971bffdcdSAmine Khaldi         msi_free(buffer);
221071bffdcdSAmine Khaldi         return row;
221171bffdcdSAmine Khaldi     }
22120272139cSwinesync     else if (!wcscmp(name, L"Time"))
221371bffdcdSAmine Khaldi     {
221471bffdcdSAmine Khaldi         length = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER, NULL, NULL, NULL, 0);
221571bffdcdSAmine Khaldi         if (!length)
221671bffdcdSAmine Khaldi             return NULL;
221771bffdcdSAmine Khaldi         buffer = msi_alloc(length * sizeof(WCHAR));
2218fec16ab0SAmine Khaldi         GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER, NULL, NULL, buffer, length);
221971bffdcdSAmine Khaldi 
222071bffdcdSAmine Khaldi         row = MSI_CreateRecord(1);
222171bffdcdSAmine Khaldi         if (!row)
2222f8b992f2SAmine Khaldi         {
2223f8b992f2SAmine Khaldi             msi_free(buffer);
222471bffdcdSAmine Khaldi             return NULL;
2225f8b992f2SAmine Khaldi         }
222671bffdcdSAmine Khaldi         MSI_RecordSetStringW(row, 1, buffer);
222771bffdcdSAmine Khaldi         msi_free(buffer);
222871bffdcdSAmine Khaldi         return row;
222971bffdcdSAmine Khaldi     }
223071bffdcdSAmine Khaldi 
2231c2c66affSColin Finck     rec = MSI_CreateRecord(1);
2232c2c66affSColin Finck     if (!rec)
2233c2c66affSColin Finck         return NULL;
2234c2c66affSColin Finck 
2235c2c66affSColin Finck     MSI_RecordSetStringW(rec, 1, name);
2236c2c66affSColin Finck 
22370272139cSwinesync     r = MSI_DatabaseOpenViewW(db, L"SELECT `Value` FROM `_Property` WHERE `_Property`=?", &view);
2238c2c66affSColin Finck     if (r == ERROR_SUCCESS)
2239c2c66affSColin Finck     {
2240c2c66affSColin Finck         MSI_ViewExecute(view, rec);
2241c2c66affSColin Finck         MSI_ViewFetch(view, &row);
2242c2c66affSColin Finck         MSI_ViewClose(view);
2243c2c66affSColin Finck         msiobj_release(&view->hdr);
2244c2c66affSColin Finck     }
2245c2c66affSColin Finck     msiobj_release(&rec->hdr);
2246c2c66affSColin Finck     return row;
2247c2c66affSColin Finck }
2248c2c66affSColin Finck 
2249c2c66affSColin Finck /* internal function, not compatible with MsiGetPropertyW */
2250c2c66affSColin Finck UINT msi_get_property( MSIDATABASE *db, LPCWSTR szName,
2251c2c66affSColin Finck                        LPWSTR szValueBuf, LPDWORD pchValueBuf )
2252c2c66affSColin Finck {
2253c2c66affSColin Finck     MSIRECORD *row;
2254c2c66affSColin Finck     UINT rc = ERROR_FUNCTION_FAILED;
2255c2c66affSColin Finck 
2256c2c66affSColin Finck     TRACE("%p %s %p %p\n", db, debugstr_w(szName), szValueBuf, pchValueBuf);
2257c2c66affSColin Finck 
2258c2c66affSColin Finck     row = msi_get_property_row( db, szName );
2259c2c66affSColin Finck 
2260c2c66affSColin Finck     if (*pchValueBuf > 0)
2261c2c66affSColin Finck         szValueBuf[0] = 0;
2262c2c66affSColin Finck 
2263c2c66affSColin Finck     if (row)
2264c2c66affSColin Finck     {
2265c2c66affSColin Finck         rc = MSI_RecordGetStringW(row, 1, szValueBuf, pchValueBuf);
2266c2c66affSColin Finck         msiobj_release(&row->hdr);
2267c2c66affSColin Finck     }
2268c2c66affSColin Finck 
2269c2c66affSColin Finck     if (rc == ERROR_SUCCESS)
2270c2c66affSColin Finck         TRACE("returning %s for property %s\n", debugstr_wn(szValueBuf, *pchValueBuf),
2271c2c66affSColin Finck             debugstr_w(szName));
2272c2c66affSColin Finck     else if (rc == ERROR_MORE_DATA)
227302f995b2Swinesync         TRACE( "need %lu sized buffer for %s\n", *pchValueBuf, debugstr_w(szName) );
2274c2c66affSColin Finck     else
2275c2c66affSColin Finck     {
2276c2c66affSColin Finck         *pchValueBuf = 0;
2277c2c66affSColin Finck         TRACE("property %s not found\n", debugstr_w(szName));
2278c2c66affSColin Finck     }
2279c2c66affSColin Finck 
2280c2c66affSColin Finck     return rc;
2281c2c66affSColin Finck }
2282c2c66affSColin Finck 
2283c2c66affSColin Finck LPWSTR msi_dup_property(MSIDATABASE *db, LPCWSTR prop)
2284c2c66affSColin Finck {
2285c2c66affSColin Finck     DWORD sz = 0;
2286c2c66affSColin Finck     LPWSTR str;
2287c2c66affSColin Finck     UINT r;
2288c2c66affSColin Finck 
2289c2c66affSColin Finck     r = msi_get_property(db, prop, NULL, &sz);
2290c2c66affSColin Finck     if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
2291c2c66affSColin Finck         return NULL;
2292c2c66affSColin Finck 
2293c2c66affSColin Finck     sz++;
2294c2c66affSColin Finck     str = msi_alloc(sz * sizeof(WCHAR));
2295c2c66affSColin Finck     r = msi_get_property(db, prop, str, &sz);
2296c2c66affSColin Finck     if (r != ERROR_SUCCESS)
2297c2c66affSColin Finck     {
2298c2c66affSColin Finck         msi_free(str);
2299c2c66affSColin Finck         str = NULL;
2300c2c66affSColin Finck     }
2301c2c66affSColin Finck 
2302c2c66affSColin Finck     return str;
2303c2c66affSColin Finck }
2304c2c66affSColin Finck 
2305c2c66affSColin Finck int msi_get_property_int( MSIDATABASE *db, LPCWSTR prop, int def )
2306c2c66affSColin Finck {
2307c2c66affSColin Finck     LPWSTR str = msi_dup_property( db, prop );
2308958f1addSwinesync     int val = str ? wcstol(str, NULL, 10) : def;
2309c2c66affSColin Finck     msi_free(str);
2310c2c66affSColin Finck     return val;
2311c2c66affSColin Finck }
2312c2c66affSColin Finck 
2313e12fb503Swinesync UINT WINAPI MsiGetPropertyA(MSIHANDLE hinst, const char *name, char *buf, DWORD *sz)
2314c2c66affSColin Finck {
23150272139cSwinesync     const WCHAR *value = L"";
2316e12fb503Swinesync     MSIPACKAGE *package;
23174748b312Swinesync     MSIRECORD *row;
2318e12fb503Swinesync     WCHAR *nameW;
23194748b312Swinesync     int len = 0;
2320c2c66affSColin Finck     UINT r;
2321c2c66affSColin Finck 
2322e12fb503Swinesync     if (!name)
2323e12fb503Swinesync         return ERROR_INVALID_PARAMETER;
2324c2c66affSColin Finck 
2325e12fb503Swinesync     if (!(nameW = strdupAtoW(name)))
2326c2c66affSColin Finck         return ERROR_OUTOFMEMORY;
2327c2c66affSColin Finck 
2328e12fb503Swinesync     package = msihandle2msiinfo(hinst, MSIHANDLETYPE_PACKAGE);
2329e12fb503Swinesync     if (!package)
2330e12fb503Swinesync     {
2331e12fb503Swinesync         WCHAR *value = NULL, *tmp;
2332e12fb503Swinesync         MSIHANDLE remote;
2333e12fb503Swinesync         DWORD len;
2334e12fb503Swinesync 
2335e12fb503Swinesync         if (!(remote = msi_get_remote(hinst)))
233602726bbcSwinesync         {
23371b18dc22Swinesync             free(nameW);
2338e12fb503Swinesync             return ERROR_INVALID_HANDLE;
233902726bbcSwinesync         }
2340e12fb503Swinesync 
23412a9ae858Swinesync         __TRY
23422a9ae858Swinesync         {
2343e12fb503Swinesync             r = remote_GetProperty(remote, nameW, &value, &len);
23442a9ae858Swinesync         }
23452a9ae858Swinesync         __EXCEPT(rpc_filter)
23462a9ae858Swinesync         {
23472a9ae858Swinesync             r = GetExceptionCode();
23482a9ae858Swinesync         }
23492a9ae858Swinesync         __ENDTRY
23502a9ae858Swinesync 
23511b18dc22Swinesync         free(nameW);
235202726bbcSwinesync 
2353e12fb503Swinesync         if (!r)
2354e12fb503Swinesync         {
2355e12fb503Swinesync             /* String might contain embedded nulls.
2356e12fb503Swinesync              * Native returns the correct size but truncates the string. */
23571b18dc22Swinesync             tmp = calloc(1, (len + 1) * sizeof(WCHAR));
2358e12fb503Swinesync             if (!tmp)
2359e12fb503Swinesync             {
2360e12fb503Swinesync                 midl_user_free(value);
2361e12fb503Swinesync                 return ERROR_OUTOFMEMORY;
2362e12fb503Swinesync             }
2363958f1addSwinesync             lstrcpyW(tmp, value);
2364e12fb503Swinesync 
2365e12fb503Swinesync             r = msi_strncpyWtoA(tmp, len, buf, sz, TRUE);
2366e12fb503Swinesync 
23671b18dc22Swinesync             free(tmp);
2368e12fb503Swinesync         }
2369e12fb503Swinesync         midl_user_free(value);
2370e12fb503Swinesync         return r;
2371e12fb503Swinesync     }
2372e12fb503Swinesync 
23734748b312Swinesync     row = msi_get_property_row(package->db, nameW);
23744748b312Swinesync     if (row)
23754748b312Swinesync         value = msi_record_get_string(row, 1, &len);
2376e12fb503Swinesync 
23774748b312Swinesync     r = msi_strncpyWtoA(value, len, buf, sz, FALSE);
2378e12fb503Swinesync 
23791b18dc22Swinesync     free(nameW);
23804748b312Swinesync     if (row) msiobj_release(&row->hdr);
2381e12fb503Swinesync     msiobj_release(&package->hdr);
2382c2c66affSColin Finck     return r;
2383c2c66affSColin Finck }
2384c2c66affSColin Finck 
23854748b312Swinesync UINT WINAPI MsiGetPropertyW(MSIHANDLE hinst, const WCHAR *name, WCHAR *buf, DWORD *sz)
2386c2c66affSColin Finck {
23870272139cSwinesync     const WCHAR *value = L"";
23884748b312Swinesync     MSIPACKAGE *package;
23894748b312Swinesync     MSIRECORD *row;
23904748b312Swinesync     int len = 0;
23914748b312Swinesync     UINT r;
2392c2c66affSColin Finck 
23934748b312Swinesync     if (!name)
23944748b312Swinesync         return ERROR_INVALID_PARAMETER;
2395c2c66affSColin Finck 
23964748b312Swinesync     package = msihandle2msiinfo(hinst, MSIHANDLETYPE_PACKAGE);
23974748b312Swinesync     if (!package)
23984748b312Swinesync     {
23994748b312Swinesync         WCHAR *value = NULL, *tmp;
24004748b312Swinesync         MSIHANDLE remote;
24014748b312Swinesync         DWORD len;
24024748b312Swinesync 
24034748b312Swinesync         if (!(remote = msi_get_remote(hinst)))
24044748b312Swinesync             return ERROR_INVALID_HANDLE;
24054748b312Swinesync 
24062a9ae858Swinesync         __TRY
24072a9ae858Swinesync         {
24084748b312Swinesync             r = remote_GetProperty(remote, name, &value, &len);
24092a9ae858Swinesync         }
24102a9ae858Swinesync         __EXCEPT(rpc_filter)
24112a9ae858Swinesync         {
24122a9ae858Swinesync             r = GetExceptionCode();
24132a9ae858Swinesync         }
24142a9ae858Swinesync         __ENDTRY
24152a9ae858Swinesync 
24164748b312Swinesync         if (!r)
24174748b312Swinesync         {
24184748b312Swinesync             /* String might contain embedded nulls.
24194748b312Swinesync              * Native returns the correct size but truncates the string. */
24201b18dc22Swinesync             tmp = calloc(1, (len + 1) * sizeof(WCHAR));
24214748b312Swinesync             if (!tmp)
24224748b312Swinesync             {
24234748b312Swinesync                 midl_user_free(value);
24244748b312Swinesync                 return ERROR_OUTOFMEMORY;
24254748b312Swinesync             }
2426958f1addSwinesync             lstrcpyW(tmp, value);
24274748b312Swinesync 
24284748b312Swinesync             r = msi_strncpyW(tmp, len, buf, sz);
24294748b312Swinesync 
24301b18dc22Swinesync             free(tmp);
24314748b312Swinesync         }
24324748b312Swinesync         midl_user_free(value);
24334748b312Swinesync         return r;
24344748b312Swinesync     }
24354748b312Swinesync 
24364748b312Swinesync     row = msi_get_property_row(package->db, name);
24374748b312Swinesync     if (row)
24384748b312Swinesync         value = msi_record_get_string(row, 1, &len);
24394748b312Swinesync 
24404748b312Swinesync     r = msi_strncpyW(value, len, buf, sz);
24414748b312Swinesync 
24424748b312Swinesync     if (row) msiobj_release(&row->hdr);
24434748b312Swinesync     msiobj_release(&package->hdr);
24444748b312Swinesync     return r;
2445c2c66affSColin Finck }
2446c2c66affSColin Finck 
2447a8bc3902Swinesync MSIHANDLE __cdecl s_remote_GetActiveDatabase(MSIHANDLE hinst)
2448b74b77aaSwinesync {
24497cc54a4fSwinesync     return MsiGetActiveDatabase(hinst);
2450c2c66affSColin Finck }
2451c2c66affSColin Finck 
2452a8bc3902Swinesync UINT __cdecl s_remote_GetProperty(MSIHANDLE hinst, LPCWSTR property, LPWSTR *value, DWORD *size)
2453c2c66affSColin Finck {
245462ababd7Swinesync     WCHAR empty[1];
245562ababd7Swinesync     UINT r;
245662ababd7Swinesync 
245762ababd7Swinesync     *size = 0;
245862ababd7Swinesync     r = MsiGetPropertyW(hinst, property, empty, size);
245962ababd7Swinesync     if (r == ERROR_MORE_DATA)
246062ababd7Swinesync     {
246162ababd7Swinesync         ++*size;
246262ababd7Swinesync         *value = midl_user_allocate(*size * sizeof(WCHAR));
246362ababd7Swinesync         if (!*value)
246462ababd7Swinesync             return ERROR_OUTOFMEMORY;
246562ababd7Swinesync         r = MsiGetPropertyW(hinst, property, *value, size);
246662ababd7Swinesync     }
246762ababd7Swinesync     return r;
2468c2c66affSColin Finck }
2469c2c66affSColin Finck 
2470a8bc3902Swinesync UINT __cdecl s_remote_SetProperty(MSIHANDLE hinst, LPCWSTR property, LPCWSTR value)
2471c2c66affSColin Finck {
24723431091cSwinesync     return MsiSetPropertyW(hinst, property, value);
2473c2c66affSColin Finck }
2474c2c66affSColin Finck 
2475a8bc3902Swinesync int __cdecl s_remote_ProcessMessage(MSIHANDLE hinst, INSTALLMESSAGE message, struct wire_record *remote_rec)
2476c2c66affSColin Finck {
24772e19edd6Swinesync     MSIHANDLE rec;
24782e19edd6Swinesync     int ret;
24792e19edd6Swinesync     UINT r;
24802e19edd6Swinesync 
24812e19edd6Swinesync     if ((r = unmarshal_record(remote_rec, &rec)))
24822e19edd6Swinesync         return r;
24832e19edd6Swinesync 
24842e19edd6Swinesync     ret = MsiProcessMessage(hinst, message, rec);
24852e19edd6Swinesync 
24862e19edd6Swinesync     MsiCloseHandle(rec);
24872e19edd6Swinesync     return ret;
2488c2c66affSColin Finck }
2489c2c66affSColin Finck 
2490a8bc3902Swinesync UINT __cdecl s_remote_DoAction(MSIHANDLE hinst, LPCWSTR action)
2491c2c66affSColin Finck {
2492c65c209aSwinesync     return MsiDoActionW(hinst, action);
2493c2c66affSColin Finck }
2494c2c66affSColin Finck 
2495a8bc3902Swinesync UINT __cdecl s_remote_Sequence(MSIHANDLE hinst, LPCWSTR table, int sequence)
2496c2c66affSColin Finck {
249710abb6f6Swinesync     return MsiSequenceW(hinst, table, sequence);
2498c2c66affSColin Finck }
2499c2c66affSColin Finck 
2500a8bc3902Swinesync UINT __cdecl s_remote_GetTargetPath(MSIHANDLE hinst, LPCWSTR folder, LPWSTR *value)
2501c2c66affSColin Finck {
2502a529a627Swinesync     WCHAR empty[1];
2503a529a627Swinesync     DWORD size = 0;
2504a529a627Swinesync     UINT r;
2505a529a627Swinesync 
2506a529a627Swinesync     r = MsiGetTargetPathW(hinst, folder, empty, &size);
2507a529a627Swinesync     if (r == ERROR_MORE_DATA)
2508a529a627Swinesync     {
2509a529a627Swinesync         *value = midl_user_allocate(++size * sizeof(WCHAR));
2510a529a627Swinesync         if (!*value)
2511a529a627Swinesync             return ERROR_OUTOFMEMORY;
2512a529a627Swinesync         r = MsiGetTargetPathW(hinst, folder, *value, &size);
2513a529a627Swinesync     }
2514a529a627Swinesync     return r;
2515c2c66affSColin Finck }
2516c2c66affSColin Finck 
2517a8bc3902Swinesync UINT __cdecl s_remote_SetTargetPath(MSIHANDLE hinst, LPCWSTR folder, LPCWSTR value)
2518c2c66affSColin Finck {
2519a5e21001Swinesync     return MsiSetTargetPathW(hinst, folder, value);
2520c2c66affSColin Finck }
2521c2c66affSColin Finck 
2522a8bc3902Swinesync UINT __cdecl s_remote_GetSourcePath(MSIHANDLE hinst, LPCWSTR folder, LPWSTR *value)
2523c2c66affSColin Finck {
25244253f351Swinesync     WCHAR empty[1];
25254253f351Swinesync     DWORD size = 1;
25264253f351Swinesync     UINT r;
25274253f351Swinesync 
25284253f351Swinesync     r = MsiGetSourcePathW(hinst, folder, empty, &size);
25294253f351Swinesync     if (r == ERROR_MORE_DATA)
25304253f351Swinesync     {
25314253f351Swinesync         *value = midl_user_allocate(++size * sizeof(WCHAR));
25324253f351Swinesync         if (!*value)
25334253f351Swinesync             return ERROR_OUTOFMEMORY;
25344253f351Swinesync         r = MsiGetSourcePathW(hinst, folder, *value, &size);
25354253f351Swinesync     }
25364253f351Swinesync     return r;
2537c2c66affSColin Finck }
2538c2c66affSColin Finck 
2539a8bc3902Swinesync BOOL __cdecl s_remote_GetMode(MSIHANDLE hinst, MSIRUNMODE mode)
2540c2c66affSColin Finck {
254183bbe8c8Swinesync     return MsiGetMode(hinst, mode);
2542c2c66affSColin Finck }
2543c2c66affSColin Finck 
2544a8bc3902Swinesync UINT __cdecl s_remote_SetMode(MSIHANDLE hinst, MSIRUNMODE mode, BOOL state)
2545c2c66affSColin Finck {
25465219367eSwinesync     return MsiSetMode(hinst, mode, state);
2547c2c66affSColin Finck }
2548c2c66affSColin Finck 
2549a8bc3902Swinesync UINT __cdecl s_remote_GetFeatureState(MSIHANDLE hinst, LPCWSTR feature,
2550c2c66affSColin Finck                                     INSTALLSTATE *installed, INSTALLSTATE *action)
2551c2c66affSColin Finck {
2552ed5fbe39Swinesync     return MsiGetFeatureStateW(hinst, feature, installed, action);
2553c2c66affSColin Finck }
2554c2c66affSColin Finck 
2555a8bc3902Swinesync UINT __cdecl s_remote_SetFeatureState(MSIHANDLE hinst, LPCWSTR feature, INSTALLSTATE state)
2556c2c66affSColin Finck {
25575bbed507Swinesync     return MsiSetFeatureStateW(hinst, feature, state);
2558c2c66affSColin Finck }
2559c2c66affSColin Finck 
2560a8bc3902Swinesync UINT __cdecl s_remote_GetComponentState(MSIHANDLE hinst, LPCWSTR component,
2561c2c66affSColin Finck                                       INSTALLSTATE *installed, INSTALLSTATE *action)
2562c2c66affSColin Finck {
2563709d0f5bSwinesync     return MsiGetComponentStateW(hinst, component, installed, action);
2564c2c66affSColin Finck }
2565c2c66affSColin Finck 
2566a8bc3902Swinesync UINT __cdecl s_remote_SetComponentState(MSIHANDLE hinst, LPCWSTR component, INSTALLSTATE state)
2567c2c66affSColin Finck {
25681c8fdff2Swinesync     return MsiSetComponentStateW(hinst, component, state);
2569c2c66affSColin Finck }
2570c2c66affSColin Finck 
2571a8bc3902Swinesync LANGID __cdecl s_remote_GetLanguage(MSIHANDLE hinst)
2572c2c66affSColin Finck {
2573fdca3090Swinesync     return MsiGetLanguage(hinst);
2574c2c66affSColin Finck }
2575c2c66affSColin Finck 
2576a8bc3902Swinesync UINT __cdecl s_remote_SetInstallLevel(MSIHANDLE hinst, int level)
2577c2c66affSColin Finck {
2578d20dc08fSwinesync     return MsiSetInstallLevel(hinst, level);
2579c2c66affSColin Finck }
2580c2c66affSColin Finck 
2581a8bc3902Swinesync UINT __cdecl s_remote_FormatRecord(MSIHANDLE hinst, struct wire_record *remote_rec, LPWSTR *value)
2582c2c66affSColin Finck {
2583cde5f24cSwinesync     WCHAR empty[1];
2584c2c66affSColin Finck     DWORD size = 0;
2585cde5f24cSwinesync     MSIHANDLE rec;
2586cde5f24cSwinesync     UINT r;
2587cde5f24cSwinesync 
2588cde5f24cSwinesync     if ((r = unmarshal_record(remote_rec, &rec)))
2589cde5f24cSwinesync         return r;
2590cde5f24cSwinesync 
2591cde5f24cSwinesync     r = MsiFormatRecordW(hinst, rec, empty, &size);
2592cde5f24cSwinesync     if (r == ERROR_MORE_DATA)
2593c2c66affSColin Finck     {
2594cde5f24cSwinesync         *value = midl_user_allocate(++size * sizeof(WCHAR));
2595c2c66affSColin Finck         if (!*value)
2596eab017d1Swinesync         {
2597eab017d1Swinesync             MsiCloseHandle(rec);
2598cde5f24cSwinesync             return ERROR_OUTOFMEMORY;
2599eab017d1Swinesync         }
2600cde5f24cSwinesync         r = MsiFormatRecordW(hinst, rec, *value, &size);
2601c2c66affSColin Finck     }
2602cde5f24cSwinesync 
2603cde5f24cSwinesync     MsiCloseHandle(rec);
2604cde5f24cSwinesync     return r;
2605c2c66affSColin Finck }
2606c2c66affSColin Finck 
2607a8bc3902Swinesync MSICONDITION __cdecl s_remote_EvaluateCondition(MSIHANDLE hinst, LPCWSTR condition)
2608c2c66affSColin Finck {
260903faa107Swinesync     return MsiEvaluateConditionW(hinst, condition);
2610c2c66affSColin Finck }
2611c2c66affSColin Finck 
2612a8bc3902Swinesync UINT __cdecl s_remote_GetFeatureCost(MSIHANDLE hinst, LPCWSTR feature,
26139f3e4bbbSwinesync     MSICOSTTREE cost_tree, INSTALLSTATE state, INT *cost)
2614c2c66affSColin Finck {
26159f3e4bbbSwinesync     return MsiGetFeatureCostW(hinst, feature, cost_tree, state, cost);
2616c2c66affSColin Finck }
2617c2c66affSColin Finck 
2618a8bc3902Swinesync UINT __cdecl s_remote_EnumComponentCosts(MSIHANDLE hinst, LPCWSTR component,
261939198134Swinesync     DWORD index, INSTALLSTATE state, LPWSTR drive, INT *cost, INT *temp)
2620c2c66affSColin Finck {
262139198134Swinesync     DWORD size = 3;
262239198134Swinesync     return MsiEnumComponentCostsW(hinst, component, index, state, drive, &size, cost, temp);
2623c2c66affSColin Finck }
2624c2c66affSColin Finck 
2625c2c66affSColin Finck UINT msi_package_add_info(MSIPACKAGE *package, DWORD context, DWORD options,
2626c2c66affSColin Finck                           LPCWSTR property, LPWSTR value)
2627c2c66affSColin Finck {
2628c2c66affSColin Finck     MSISOURCELISTINFO *info;
2629c2c66affSColin Finck 
2630c2c66affSColin Finck     LIST_FOR_EACH_ENTRY( info, &package->sourcelist_info, MSISOURCELISTINFO, entry )
2631c2c66affSColin Finck     {
2632958f1addSwinesync         if (!wcscmp( info->value, value )) return ERROR_SUCCESS;
2633c2c66affSColin Finck     }
2634c2c66affSColin Finck 
2635c2c66affSColin Finck     info = msi_alloc(sizeof(MSISOURCELISTINFO));
2636c2c66affSColin Finck     if (!info)
2637c2c66affSColin Finck         return ERROR_OUTOFMEMORY;
2638c2c66affSColin Finck 
2639c2c66affSColin Finck     info->context = context;
2640c2c66affSColin Finck     info->options = options;
2641c2c66affSColin Finck     info->property = property;
2642c2c66affSColin Finck     info->value = strdupW(value);
2643c2c66affSColin Finck     list_add_head(&package->sourcelist_info, &info->entry);
2644c2c66affSColin Finck 
2645c2c66affSColin Finck     return ERROR_SUCCESS;
2646c2c66affSColin Finck }
2647c2c66affSColin Finck 
2648c2c66affSColin Finck UINT msi_package_add_media_disk(MSIPACKAGE *package, DWORD context, DWORD options,
2649c2c66affSColin Finck                                 DWORD disk_id, LPWSTR volume_label, LPWSTR disk_prompt)
2650c2c66affSColin Finck {
2651c2c66affSColin Finck     MSIMEDIADISK *disk;
2652c2c66affSColin Finck 
2653c2c66affSColin Finck     LIST_FOR_EACH_ENTRY( disk, &package->sourcelist_media, MSIMEDIADISK, entry )
2654c2c66affSColin Finck     {
2655c2c66affSColin Finck         if (disk->disk_id == disk_id) return ERROR_SUCCESS;
2656c2c66affSColin Finck     }
2657c2c66affSColin Finck 
2658c2c66affSColin Finck     disk = msi_alloc(sizeof(MSIMEDIADISK));
2659c2c66affSColin Finck     if (!disk)
2660c2c66affSColin Finck         return ERROR_OUTOFMEMORY;
2661c2c66affSColin Finck 
2662c2c66affSColin Finck     disk->context = context;
2663c2c66affSColin Finck     disk->options = options;
2664c2c66affSColin Finck     disk->disk_id = disk_id;
2665c2c66affSColin Finck     disk->volume_label = strdupW(volume_label);
2666c2c66affSColin Finck     disk->disk_prompt = strdupW(disk_prompt);
2667c2c66affSColin Finck     list_add_head(&package->sourcelist_media, &disk->entry);
2668c2c66affSColin Finck 
2669c2c66affSColin Finck     return ERROR_SUCCESS;
2670c2c66affSColin Finck }
2671