xref: /reactos/dll/win32/msi/package.c (revision f4be6dc3)
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 COBJMACROS
22*f4be6dc3SMikhail 
23f4d2571bSwinesync #ifdef __REACTOS__
24f4d2571bSwinesync #define WIN32_NO_STATUS
25f4d2571bSwinesync #endif
26c2c66affSColin Finck 
27c42b133eSAmine Khaldi #include <stdarg.h>
28c42b133eSAmine Khaldi #include "windef.h"
29c42b133eSAmine Khaldi #include "winbase.h"
30c42b133eSAmine Khaldi #include "winreg.h"
31c42b133eSAmine Khaldi #include "winnls.h"
32f4d2571bSwinesync #ifdef __REACTOS__
33f4d2571bSwinesync #include <ndk/rtlfuncs.h>
34f4d2571bSwinesync #else
35f4d2571bSwinesync #include "winternl.h"
36f4d2571bSwinesync #endif
37c42b133eSAmine Khaldi #include "shlwapi.h"
38c42b133eSAmine Khaldi #include "wingdi.h"
39c42b133eSAmine Khaldi #include "msi.h"
40c42b133eSAmine Khaldi #include "msiquery.h"
41c42b133eSAmine Khaldi #include "objidl.h"
42c42b133eSAmine Khaldi #include "wincrypt.h"
43c42b133eSAmine Khaldi #include "winuser.h"
44c42b133eSAmine Khaldi #include "wininet.h"
45c42b133eSAmine Khaldi #include "winver.h"
46c42b133eSAmine Khaldi #include "urlmon.h"
47c42b133eSAmine Khaldi #include "shlobj.h"
48c42b133eSAmine Khaldi #include "objbase.h"
49c42b133eSAmine Khaldi #include "msidefs.h"
50c42b133eSAmine Khaldi #include "sddl.h"
51c42b133eSAmine Khaldi 
5262ababd7Swinesync #include "wine/debug.h"
532a9ae858Swinesync #include "wine/exception.h"
5462ababd7Swinesync 
55c42b133eSAmine Khaldi #include "msipriv.h"
56a8bc3902Swinesync #include "winemsi_s.h"
57c42b133eSAmine Khaldi #include "resource.h"
58c2c66affSColin Finck 
59c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(msi);
60c2c66affSColin Finck 
free_feature(MSIFEATURE * feature)61c2c66affSColin Finck static void free_feature( MSIFEATURE *feature )
62c2c66affSColin Finck {
63c2c66affSColin Finck     struct list *item, *cursor;
64c2c66affSColin Finck 
65c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &feature->Children )
66c2c66affSColin Finck     {
67c2c66affSColin Finck         FeatureList *fl = LIST_ENTRY( item, FeatureList, entry );
68c2c66affSColin Finck         list_remove( &fl->entry );
69*f4be6dc3SMikhail         free( fl );
70c2c66affSColin Finck     }
71c2c66affSColin Finck 
72c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &feature->Components )
73c2c66affSColin Finck     {
74c2c66affSColin Finck         ComponentList *cl = LIST_ENTRY( item, ComponentList, entry );
75c2c66affSColin Finck         list_remove( &cl->entry );
76*f4be6dc3SMikhail         free( cl );
77c2c66affSColin Finck     }
78*f4be6dc3SMikhail     free( feature->Feature );
79*f4be6dc3SMikhail     free( feature->Feature_Parent );
80*f4be6dc3SMikhail     free( feature->Directory );
81*f4be6dc3SMikhail     free( feature->Description );
82*f4be6dc3SMikhail     free( feature->Title );
83*f4be6dc3SMikhail     free( feature );
84c2c66affSColin Finck }
85c2c66affSColin Finck 
free_folder(MSIFOLDER * folder)86c2c66affSColin Finck static void free_folder( MSIFOLDER *folder )
87c2c66affSColin Finck {
88c2c66affSColin Finck     struct list *item, *cursor;
89c2c66affSColin Finck 
90c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &folder->children )
91c2c66affSColin Finck     {
92c2c66affSColin Finck         FolderList *fl = LIST_ENTRY( item, FolderList, entry );
93c2c66affSColin Finck         list_remove( &fl->entry );
94*f4be6dc3SMikhail         free( fl );
95c2c66affSColin Finck     }
96*f4be6dc3SMikhail     free( folder->Parent );
97*f4be6dc3SMikhail     free( folder->Directory );
98*f4be6dc3SMikhail     free( folder->TargetDefault );
99*f4be6dc3SMikhail     free( folder->SourceLongPath );
100*f4be6dc3SMikhail     free( folder->SourceShortPath );
101*f4be6dc3SMikhail     free( folder->ResolvedTarget );
102*f4be6dc3SMikhail     free( folder->ResolvedSource );
103*f4be6dc3SMikhail     free( folder );
104c2c66affSColin Finck }
105c2c66affSColin Finck 
free_extension(MSIEXTENSION * ext)106c2c66affSColin Finck static void free_extension( MSIEXTENSION *ext )
107c2c66affSColin Finck {
108c2c66affSColin Finck     struct list *item, *cursor;
109c2c66affSColin Finck 
110c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &ext->verbs )
111c2c66affSColin Finck     {
112c2c66affSColin Finck         MSIVERB *verb = LIST_ENTRY( item, MSIVERB, entry );
113c2c66affSColin Finck 
114c2c66affSColin Finck         list_remove( &verb->entry );
115*f4be6dc3SMikhail         free( verb->Verb );
116*f4be6dc3SMikhail         free( verb->Command );
117*f4be6dc3SMikhail         free( verb->Argument );
118*f4be6dc3SMikhail         free( verb );
119c2c66affSColin Finck     }
120c2c66affSColin Finck 
121*f4be6dc3SMikhail     free( ext->Extension );
122*f4be6dc3SMikhail     free( ext->ProgIDText );
123*f4be6dc3SMikhail     free( ext );
124c2c66affSColin Finck }
125c2c66affSColin Finck 
free_assembly(MSIASSEMBLY * assembly)126c2c66affSColin Finck static void free_assembly( MSIASSEMBLY *assembly )
127c2c66affSColin Finck {
128*f4be6dc3SMikhail     free( assembly->feature );
129*f4be6dc3SMikhail     free( assembly->manifest );
130*f4be6dc3SMikhail     free( assembly->application );
131*f4be6dc3SMikhail     free( assembly->display_name );
132c2c66affSColin Finck     if (assembly->tempdir) RemoveDirectoryW( assembly->tempdir );
133*f4be6dc3SMikhail     free( assembly->tempdir );
134*f4be6dc3SMikhail     free( assembly );
135c2c66affSColin Finck }
136c2c66affSColin Finck 
msi_free_action_script(MSIPACKAGE * package,UINT script)137c2c66affSColin Finck void msi_free_action_script( MSIPACKAGE *package, UINT script )
138c2c66affSColin Finck {
139c2c66affSColin Finck     UINT i;
140f8b992f2SAmine Khaldi     for (i = 0; i < package->script_actions_count[script]; i++)
141*f4be6dc3SMikhail         free( package->script_actions[script][i] );
142c2c66affSColin Finck 
143*f4be6dc3SMikhail     free( package->script_actions[script] );
144f8b992f2SAmine Khaldi     package->script_actions[script] = NULL;
145f8b992f2SAmine Khaldi     package->script_actions_count[script] = 0;
146c2c66affSColin Finck }
147c2c66affSColin Finck 
free_package_structures(MSIPACKAGE * package)148c2c66affSColin Finck static void free_package_structures( MSIPACKAGE *package )
149c2c66affSColin Finck {
150c2c66affSColin Finck     struct list *item, *cursor;
151f8b992f2SAmine Khaldi     int i;
152c2c66affSColin Finck 
153c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->features )
154c2c66affSColin Finck     {
155c2c66affSColin Finck         MSIFEATURE *feature = LIST_ENTRY( item, MSIFEATURE, entry );
156c2c66affSColin Finck         list_remove( &feature->entry );
157c2c66affSColin Finck         free_feature( feature );
158c2c66affSColin Finck     }
159c2c66affSColin Finck 
160c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->folders )
161c2c66affSColin Finck     {
162c2c66affSColin Finck         MSIFOLDER *folder = LIST_ENTRY( item, MSIFOLDER, entry );
163c2c66affSColin Finck         list_remove( &folder->entry );
164c2c66affSColin Finck         free_folder( folder );
165c2c66affSColin Finck     }
166c2c66affSColin Finck 
167c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->files )
168c2c66affSColin Finck     {
169c2c66affSColin Finck         MSIFILE *file = LIST_ENTRY( item, MSIFILE, entry );
170c2c66affSColin Finck 
171c2c66affSColin Finck         list_remove( &file->entry );
172*f4be6dc3SMikhail         free( file->File );
173*f4be6dc3SMikhail         free( file->FileName );
174*f4be6dc3SMikhail         free( file->ShortName );
175*f4be6dc3SMikhail         free( file->LongName );
176*f4be6dc3SMikhail         free( file->Version );
177*f4be6dc3SMikhail         free( file->Language );
178c2c66affSColin Finck         if (msi_is_global_assembly( file->Component )) DeleteFileW( file->TargetPath );
179*f4be6dc3SMikhail         free( file->TargetPath );
180*f4be6dc3SMikhail         free( file );
181c2c66affSColin Finck     }
182c2c66affSColin Finck 
183c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->components )
184c2c66affSColin Finck     {
185c2c66affSColin Finck         MSICOMPONENT *comp = LIST_ENTRY( item, MSICOMPONENT, entry );
186c2c66affSColin Finck 
187c2c66affSColin Finck         list_remove( &comp->entry );
188*f4be6dc3SMikhail         free( comp->Component );
189*f4be6dc3SMikhail         free( comp->ComponentId );
190*f4be6dc3SMikhail         free( comp->Directory );
191*f4be6dc3SMikhail         free( comp->Condition );
192*f4be6dc3SMikhail         free( comp->KeyPath );
193*f4be6dc3SMikhail         free( comp->FullKeypath );
194c2c66affSColin Finck         if (comp->assembly) free_assembly( comp->assembly );
195*f4be6dc3SMikhail         free( comp );
196c2c66affSColin Finck     }
197c2c66affSColin Finck 
198c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->filepatches )
199c2c66affSColin Finck     {
200c2c66affSColin Finck         MSIFILEPATCH *patch = LIST_ENTRY( item, MSIFILEPATCH, entry );
201c2c66affSColin Finck 
202c2c66affSColin Finck         list_remove( &patch->entry );
203*f4be6dc3SMikhail         free( patch->path );
204*f4be6dc3SMikhail         free( patch );
205c2c66affSColin Finck     }
206c2c66affSColin Finck 
207c2c66affSColin Finck     /* clean up extension, progid, class and verb structures */
208c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->classes )
209c2c66affSColin Finck     {
210c2c66affSColin Finck         MSICLASS *cls = LIST_ENTRY( item, MSICLASS, entry );
211c2c66affSColin Finck 
212c2c66affSColin Finck         list_remove( &cls->entry );
213*f4be6dc3SMikhail         free( cls->clsid );
214*f4be6dc3SMikhail         free( cls->Context );
215*f4be6dc3SMikhail         free( cls->Description );
216*f4be6dc3SMikhail         free( cls->FileTypeMask );
217*f4be6dc3SMikhail         free( cls->IconPath );
218*f4be6dc3SMikhail         free( cls->DefInprocHandler );
219*f4be6dc3SMikhail         free( cls->DefInprocHandler32 );
220*f4be6dc3SMikhail         free( cls->Argument );
221*f4be6dc3SMikhail         free( cls->ProgIDText );
222*f4be6dc3SMikhail         free( cls );
223c2c66affSColin Finck     }
224c2c66affSColin Finck 
225c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->extensions )
226c2c66affSColin Finck     {
227c2c66affSColin Finck         MSIEXTENSION *ext = LIST_ENTRY( item, MSIEXTENSION, entry );
228c2c66affSColin Finck 
229c2c66affSColin Finck         list_remove( &ext->entry );
230c2c66affSColin Finck         free_extension( ext );
231c2c66affSColin Finck     }
232c2c66affSColin Finck 
233c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->progids )
234c2c66affSColin Finck     {
235c2c66affSColin Finck         MSIPROGID *progid = LIST_ENTRY( item, MSIPROGID, entry );
236c2c66affSColin Finck 
237c2c66affSColin Finck         list_remove( &progid->entry );
238*f4be6dc3SMikhail         free( progid->ProgID );
239*f4be6dc3SMikhail         free( progid->Description );
240*f4be6dc3SMikhail         free( progid->IconPath );
241*f4be6dc3SMikhail         free( progid );
242c2c66affSColin Finck     }
243c2c66affSColin Finck 
244c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->mimes )
245c2c66affSColin Finck     {
246c2c66affSColin Finck         MSIMIME *mt = LIST_ENTRY( item, MSIMIME, entry );
247c2c66affSColin Finck 
248c2c66affSColin Finck         list_remove( &mt->entry );
249*f4be6dc3SMikhail         free( mt->suffix );
250*f4be6dc3SMikhail         free( mt->clsid );
251*f4be6dc3SMikhail         free( mt->ContentType );
252*f4be6dc3SMikhail         free( mt );
253c2c66affSColin Finck     }
254c2c66affSColin Finck 
255c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->appids )
256c2c66affSColin Finck     {
257c2c66affSColin Finck         MSIAPPID *appid = LIST_ENTRY( item, MSIAPPID, entry );
258c2c66affSColin Finck 
259c2c66affSColin Finck         list_remove( &appid->entry );
260*f4be6dc3SMikhail         free( appid->AppID );
261*f4be6dc3SMikhail         free( appid->RemoteServerName );
262*f4be6dc3SMikhail         free( appid->LocalServer );
263*f4be6dc3SMikhail         free( appid->ServiceParameters );
264*f4be6dc3SMikhail         free( appid->DllSurrogate );
265*f4be6dc3SMikhail         free( appid );
266c2c66affSColin Finck     }
267c2c66affSColin Finck 
268c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_info )
269c2c66affSColin Finck     {
270c2c66affSColin Finck         MSISOURCELISTINFO *info = LIST_ENTRY( item, MSISOURCELISTINFO, entry );
271c2c66affSColin Finck 
272c2c66affSColin Finck         list_remove( &info->entry );
273*f4be6dc3SMikhail         free( info->value );
274*f4be6dc3SMikhail         free( info );
275c2c66affSColin Finck     }
276c2c66affSColin Finck 
277c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_media )
278c2c66affSColin Finck     {
279c2c66affSColin Finck         MSIMEDIADISK *info = LIST_ENTRY( item, MSIMEDIADISK, entry );
280c2c66affSColin Finck 
281c2c66affSColin Finck         list_remove( &info->entry );
282*f4be6dc3SMikhail         free( info->volume_label );
283*f4be6dc3SMikhail         free( info->disk_prompt );
284*f4be6dc3SMikhail         free( info );
285c2c66affSColin Finck     }
286c2c66affSColin Finck 
287c2c66affSColin Finck     for (i = 0; i < SCRIPT_MAX; i++)
288c2c66affSColin Finck         msi_free_action_script( package, i );
289c2c66affSColin Finck 
290f8b992f2SAmine Khaldi     for (i = 0; i < package->unique_actions_count; i++)
291*f4be6dc3SMikhail         free( package->unique_actions[i] );
292*f4be6dc3SMikhail     free( package->unique_actions );
293c2c66affSColin Finck 
294c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->binaries )
295c2c66affSColin Finck     {
296c2c66affSColin Finck         MSIBINARY *binary = LIST_ENTRY( item, MSIBINARY, entry );
297c2c66affSColin Finck 
298c2c66affSColin Finck         list_remove( &binary->entry );
299c2c66affSColin Finck         if (!DeleteFileW( binary->tmpfile ))
30002f995b2Swinesync             ERR( "failed to delete %s (%lu)\n", debugstr_w(binary->tmpfile), GetLastError() );
301*f4be6dc3SMikhail         free( binary->source );
302*f4be6dc3SMikhail         free( binary->tmpfile );
303*f4be6dc3SMikhail         free( binary );
304c2c66affSColin Finck     }
305c2c66affSColin Finck 
306c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->cabinet_streams )
307c2c66affSColin Finck     {
308c2c66affSColin Finck         MSICABINETSTREAM *cab = LIST_ENTRY( item, MSICABINETSTREAM, entry );
309c2c66affSColin Finck 
310c2c66affSColin Finck         list_remove( &cab->entry );
311c2c66affSColin Finck         IStorage_Release( cab->storage );
312*f4be6dc3SMikhail         free( cab->stream );
313*f4be6dc3SMikhail         free( cab );
314c2c66affSColin Finck     }
315c2c66affSColin Finck 
316c2c66affSColin Finck     LIST_FOR_EACH_SAFE( item, cursor, &package->patches )
317c2c66affSColin Finck     {
318c2c66affSColin Finck         MSIPATCHINFO *patch = LIST_ENTRY( item, MSIPATCHINFO, entry );
319c2c66affSColin Finck 
320c2c66affSColin Finck         list_remove( &patch->entry );
321c2c66affSColin Finck         if (patch->delete_on_close && !DeleteFileW( patch->localfile ))
322c2c66affSColin Finck         {
32302f995b2Swinesync             ERR( "failed to delete %s (%lu)\n", debugstr_w(patch->localfile), GetLastError() );
324c2c66affSColin Finck         }
325c2c66affSColin Finck         msi_free_patchinfo( patch );
326c2c66affSColin Finck     }
327c2c66affSColin Finck 
328*f4be6dc3SMikhail     free( package->PackagePath );
329*f4be6dc3SMikhail     free( package->ProductCode );
330*f4be6dc3SMikhail     free( package->ActionFormat );
331*f4be6dc3SMikhail     free( package->LastAction );
332*f4be6dc3SMikhail     free( package->LastActionTemplate );
333*f4be6dc3SMikhail     free( package->langids );
334c2c66affSColin Finck 
335c2c66affSColin Finck     /* cleanup control event subscriptions */
336c2c66affSColin Finck     msi_event_cleanup_all_subscriptions( package );
337c2c66affSColin Finck }
338c2c66affSColin Finck 
MSI_FreePackage(MSIOBJECTHDR * arg)339c2c66affSColin Finck static void MSI_FreePackage( MSIOBJECTHDR *arg)
340c2c66affSColin Finck {
341c2c66affSColin Finck     MSIPACKAGE *package = (MSIPACKAGE *)arg;
342c2c66affSColin Finck 
343c2c66affSColin Finck     msi_destroy_assembly_caches( package );
344c2c66affSColin Finck 
345c2c66affSColin Finck     if( package->dialog )
346c2c66affSColin Finck         msi_dialog_destroy( package->dialog );
347c2c66affSColin Finck 
348c2c66affSColin Finck     msiobj_release( &package->db->hdr );
349c2c66affSColin Finck     free_package_structures(package);
350c2c66affSColin Finck     CloseHandle( package->log_file );
3510a327bfeSwinesync     if (package->rpc_server_started)
3520a327bfeSwinesync         RpcServerUnregisterIf(s_IWineMsiRemote_v0_0_s_ifspec, NULL, FALSE);
353dfdb6d10Swinesync     if (rpc_handle)
354dfdb6d10Swinesync         RpcBindingFree(&rpc_handle);
35582decec5Swinesync     if (package->custom_server_32_process)
35682decec5Swinesync         custom_stop_server(package->custom_server_32_process, package->custom_server_32_pipe);
35782decec5Swinesync     if (package->custom_server_64_process)
35882decec5Swinesync         custom_stop_server(package->custom_server_64_process, package->custom_server_64_pipe);
359c2c66affSColin Finck 
360c2c66affSColin Finck     if (package->delete_on_close) DeleteFileW( package->localfile );
361*f4be6dc3SMikhail     free( package->localfile );
36271bffdcdSAmine Khaldi     MSI_ProcessMessage(NULL, INSTALLMESSAGE_TERMINATE, 0);
363c2c66affSColin Finck }
364c2c66affSColin Finck 
create_temp_property_table(MSIPACKAGE * package)365c2c66affSColin Finck static UINT create_temp_property_table(MSIPACKAGE *package)
366c2c66affSColin Finck {
367c2c66affSColin Finck     MSIQUERY *view;
368c2c66affSColin Finck     UINT rc;
369c2c66affSColin Finck 
3700272139cSwinesync     rc = MSI_DatabaseOpenViewW(package->db, L"CREATE TABLE `_Property` ( `_Property` CHAR(56) NOT NULL TEMPORARY, "
3710272139cSwinesync                                             L"`Value` CHAR(98) NOT NULL TEMPORARY PRIMARY KEY `_Property`) HOLD", &view);
372c2c66affSColin Finck     if (rc != ERROR_SUCCESS)
373c2c66affSColin Finck         return rc;
374c2c66affSColin Finck 
375c2c66affSColin Finck     rc = MSI_ViewExecute(view, 0);
376c2c66affSColin Finck     MSI_ViewClose(view);
377c2c66affSColin Finck     msiobj_release(&view->hdr);
378c2c66affSColin Finck     return rc;
379c2c66affSColin Finck }
380c2c66affSColin Finck 
msi_clone_properties(MSIDATABASE * db)381c2c66affSColin Finck UINT msi_clone_properties( MSIDATABASE *db )
382c2c66affSColin Finck {
383c2c66affSColin Finck     MSIQUERY *view_select;
384c2c66affSColin Finck     UINT rc;
385c2c66affSColin Finck 
3860272139cSwinesync     rc = MSI_DatabaseOpenViewW( db, L"SELECT * FROM `Property`", &view_select );
387c2c66affSColin Finck     if (rc != ERROR_SUCCESS)
388c2c66affSColin Finck         return rc;
389c2c66affSColin Finck 
390c2c66affSColin Finck     rc = MSI_ViewExecute( view_select, 0 );
391c2c66affSColin Finck     if (rc != ERROR_SUCCESS)
392c2c66affSColin Finck     {
393c2c66affSColin Finck         MSI_ViewClose( view_select );
394c2c66affSColin Finck         msiobj_release( &view_select->hdr );
395c2c66affSColin Finck         return rc;
396c2c66affSColin Finck     }
397c2c66affSColin Finck 
398c2c66affSColin Finck     while (1)
399c2c66affSColin Finck     {
400c2c66affSColin Finck         MSIQUERY *view_insert, *view_update;
401c2c66affSColin Finck         MSIRECORD *rec_select;
402c2c66affSColin Finck 
403c2c66affSColin Finck         rc = MSI_ViewFetch( view_select, &rec_select );
404c2c66affSColin Finck         if (rc != ERROR_SUCCESS)
405c2c66affSColin Finck             break;
406c2c66affSColin Finck 
4070272139cSwinesync         rc = MSI_DatabaseOpenViewW( db, L"INSERT INTO `_Property` (`_Property`,`Value`) VALUES (?,?)", &view_insert );
408c2c66affSColin Finck         if (rc != ERROR_SUCCESS)
409c2c66affSColin Finck         {
410c2c66affSColin Finck             msiobj_release( &rec_select->hdr );
411c2c66affSColin Finck             continue;
412c2c66affSColin Finck         }
413c2c66affSColin Finck 
414c2c66affSColin Finck         rc = MSI_ViewExecute( view_insert, rec_select );
415c2c66affSColin Finck         MSI_ViewClose( view_insert );
416c2c66affSColin Finck         msiobj_release( &view_insert->hdr );
417c2c66affSColin Finck         if (rc != ERROR_SUCCESS)
418c2c66affSColin Finck         {
419c2c66affSColin Finck             MSIRECORD *rec_update;
420c2c66affSColin Finck 
421c2c66affSColin Finck             TRACE("insert failed, trying update\n");
422c2c66affSColin Finck 
4230272139cSwinesync             rc = MSI_DatabaseOpenViewW( db, L"UPDATE `_Property` SET `Value` = ? WHERE `_Property` = ?", &view_update );
424c2c66affSColin Finck             if (rc != ERROR_SUCCESS)
425c2c66affSColin Finck             {
426c2c66affSColin Finck                 WARN("open view failed %u\n", rc);
427c2c66affSColin Finck                 msiobj_release( &rec_select->hdr );
428c2c66affSColin Finck                 continue;
429c2c66affSColin Finck             }
430c2c66affSColin Finck 
431c2c66affSColin Finck             rec_update = MSI_CreateRecord( 2 );
432c2c66affSColin Finck             MSI_RecordCopyField( rec_select, 1, rec_update, 2 );
433c2c66affSColin Finck             MSI_RecordCopyField( rec_select, 2, rec_update, 1 );
434c2c66affSColin Finck             rc = MSI_ViewExecute( view_update, rec_update );
435c2c66affSColin Finck             if (rc != ERROR_SUCCESS)
436c2c66affSColin Finck                 WARN("update failed %u\n", rc);
437c2c66affSColin Finck 
438c2c66affSColin Finck             MSI_ViewClose( view_update );
439c2c66affSColin Finck             msiobj_release( &view_update->hdr );
440c2c66affSColin Finck             msiobj_release( &rec_update->hdr );
441c2c66affSColin Finck         }
442c2c66affSColin Finck 
443c2c66affSColin Finck         msiobj_release( &rec_select->hdr );
444c2c66affSColin Finck     }
445c2c66affSColin Finck 
446c2c66affSColin Finck     MSI_ViewClose( view_select );
447c2c66affSColin Finck     msiobj_release( &view_select->hdr );
448c2c66affSColin Finck     return rc;
449c2c66affSColin Finck }
450c2c66affSColin Finck 
451c2c66affSColin Finck /*
452c2c66affSColin Finck  * set_installed_prop
453c2c66affSColin Finck  *
454c2c66affSColin Finck  * Sets the "Installed" property to indicate that
455c2c66affSColin Finck  *  the product is installed for the current user.
456c2c66affSColin Finck  */
set_installed_prop(MSIPACKAGE * package)457c2c66affSColin Finck static UINT set_installed_prop( MSIPACKAGE *package )
458c2c66affSColin Finck {
459c2c66affSColin Finck     HKEY hkey;
460c2c66affSColin Finck     UINT r;
461c2c66affSColin Finck 
462c2c66affSColin Finck     if (!package->ProductCode) return ERROR_FUNCTION_FAILED;
463c2c66affSColin Finck 
464c2c66affSColin Finck     r = MSIREG_OpenUninstallKey( package->ProductCode, package->platform, &hkey, FALSE );
465c2c66affSColin Finck     if (r == ERROR_SUCCESS)
466c2c66affSColin Finck     {
467c2c66affSColin Finck         RegCloseKey( hkey );
4680272139cSwinesync         msi_set_property( package->db, L"Installed", L"1", -1 );
469c2c66affSColin Finck     }
470c2c66affSColin Finck     return r;
471c2c66affSColin Finck }
472c2c66affSColin Finck 
set_user_sid_prop(MSIPACKAGE * package)473c2c66affSColin Finck static UINT set_user_sid_prop( MSIPACKAGE *package )
474c2c66affSColin Finck {
475c2c66affSColin Finck     SID_NAME_USE use;
476c2c66affSColin Finck     LPWSTR user_name;
477c2c66affSColin Finck     LPWSTR sid_str = NULL, dom = NULL;
478c2c66affSColin Finck     DWORD size, dom_size;
479c2c66affSColin Finck     PSID psid = NULL;
480c2c66affSColin Finck     UINT r = ERROR_FUNCTION_FAILED;
481c2c66affSColin Finck 
482c2c66affSColin Finck     size = 0;
483c2c66affSColin Finck     GetUserNameW( NULL, &size );
484c2c66affSColin Finck 
485*f4be6dc3SMikhail     user_name = malloc( (size + 1) * sizeof(WCHAR) );
486c2c66affSColin Finck     if (!user_name)
487c2c66affSColin Finck         return ERROR_OUTOFMEMORY;
488c2c66affSColin Finck 
489c2c66affSColin Finck     if (!GetUserNameW( user_name, &size ))
490c2c66affSColin Finck         goto done;
491c2c66affSColin Finck 
492c2c66affSColin Finck     size = 0;
493c2c66affSColin Finck     dom_size = 0;
494c2c66affSColin Finck     LookupAccountNameW( NULL, user_name, NULL, &size, NULL, &dom_size, &use );
495c2c66affSColin Finck 
496*f4be6dc3SMikhail     psid = malloc( size );
497*f4be6dc3SMikhail     dom = malloc( dom_size * sizeof (WCHAR) );
498c2c66affSColin Finck     if (!psid || !dom)
499c2c66affSColin Finck     {
500c2c66affSColin Finck         r = ERROR_OUTOFMEMORY;
501c2c66affSColin Finck         goto done;
502c2c66affSColin Finck     }
503c2c66affSColin Finck 
504c2c66affSColin Finck     if (!LookupAccountNameW( NULL, user_name, psid, &size, dom, &dom_size, &use ))
505c2c66affSColin Finck         goto done;
506c2c66affSColin Finck 
507c2c66affSColin Finck     if (!ConvertSidToStringSidW( psid, &sid_str ))
508c2c66affSColin Finck         goto done;
509c2c66affSColin Finck 
5100272139cSwinesync     r = msi_set_property( package->db, L"UserSID", sid_str, -1 );
511c2c66affSColin Finck 
512c2c66affSColin Finck done:
513c2c66affSColin Finck     LocalFree( sid_str );
514*f4be6dc3SMikhail     free( dom );
515*f4be6dc3SMikhail     free( psid );
516*f4be6dc3SMikhail     free( user_name );
517c2c66affSColin Finck 
518c2c66affSColin Finck     return r;
519c2c66affSColin Finck }
520c2c66affSColin Finck 
get_fusion_filename(MSIPACKAGE * package)521c2c66affSColin Finck static LPWSTR get_fusion_filename(MSIPACKAGE *package)
522c2c66affSColin Finck {
523c42b133eSAmine Khaldi     HKEY netsetup, hkey;
524c2c66affSColin Finck     LONG res;
525c42b133eSAmine Khaldi     DWORD size, len, type;
526c42b133eSAmine Khaldi     WCHAR windir[MAX_PATH], path[MAX_PATH], *filename = NULL;
527c2c66affSColin Finck 
5280272139cSwinesync     res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\NET Framework Setup\\NDP", 0, KEY_CREATE_SUB_KEY,
5290272139cSwinesync                         &netsetup);
530c2c66affSColin Finck     if (res != ERROR_SUCCESS)
531c2c66affSColin Finck         return NULL;
532c2c66affSColin Finck 
5330272139cSwinesync     if (!RegCreateKeyExW(netsetup, L"v4\\Client", 0, NULL, 0, KEY_QUERY_VALUE, NULL, &hkey, NULL))
534c42b133eSAmine Khaldi     {
5358c1eae24Swinesync         size = sizeof(path);
5360272139cSwinesync         if (!RegQueryValueExW(hkey, L"InstallPath", NULL, &type, (BYTE *)path, &size))
537c42b133eSAmine Khaldi         {
5380272139cSwinesync             len = lstrlenW(path) + lstrlenW(L"fusion.dll") + 2;
539*f4be6dc3SMikhail             if (!(filename = malloc(len * sizeof(WCHAR)))) return NULL;
540c42b133eSAmine Khaldi 
541958f1addSwinesync             lstrcpyW(filename, path);
542a3e22d89Swinesync             lstrcatW(filename, L"\\");
5430272139cSwinesync             lstrcatW(filename, L"fusion.dll");
544c42b133eSAmine Khaldi             if (GetFileAttributesW(filename) != INVALID_FILE_ATTRIBUTES)
545c42b133eSAmine Khaldi             {
546c42b133eSAmine Khaldi                 TRACE( "found %s\n", debugstr_w(filename) );
547c42b133eSAmine Khaldi                 RegCloseKey(hkey);
548c42b133eSAmine Khaldi                 RegCloseKey(netsetup);
549c42b133eSAmine Khaldi                 return filename;
550c42b133eSAmine Khaldi             }
551c42b133eSAmine Khaldi         }
552c42b133eSAmine Khaldi         RegCloseKey(hkey);
553c42b133eSAmine Khaldi     }
554c42b133eSAmine Khaldi 
5550272139cSwinesync     if (!RegCreateKeyExW(netsetup, L"v2.0.50727", 0, NULL, 0, KEY_QUERY_VALUE, NULL, &hkey, NULL))
556c42b133eSAmine Khaldi     {
557c42b133eSAmine Khaldi         RegCloseKey(hkey);
558c2c66affSColin Finck         GetWindowsDirectoryW(windir, MAX_PATH);
5590272139cSwinesync         len = lstrlenW(windir) + lstrlenW(L"Microsoft.NET\\Framework\\") + lstrlenW(L"v2.0.50727") +
5600272139cSwinesync               lstrlenW(L"fusion.dll") + 3;
561*f4be6dc3SMikhail         free(filename);
562*f4be6dc3SMikhail         if (!(filename = malloc(len * sizeof(WCHAR)))) return NULL;
563c2c66affSColin Finck 
564958f1addSwinesync         lstrcpyW(filename, windir);
5650272139cSwinesync         lstrcatW(filename, L"\\");
5660272139cSwinesync         lstrcatW(filename, L"Microsoft.NET\\Framework\\");
5670272139cSwinesync         lstrcatW(filename, L"v2.0.50727");
5680272139cSwinesync         lstrcatW(filename, L"\\");
5690272139cSwinesync         lstrcatW(filename, L"fusion.dll");
570c42b133eSAmine Khaldi         if (GetFileAttributesW(filename) != INVALID_FILE_ATTRIBUTES)
571c2c66affSColin Finck         {
572c42b133eSAmine Khaldi             TRACE( "found %s\n", debugstr_w(filename) );
573c42b133eSAmine Khaldi             RegCloseKey(netsetup);
574c42b133eSAmine Khaldi             return filename;
575c2c66affSColin Finck         }
576c2c66affSColin Finck     }
577c2c66affSColin Finck 
578c2c66affSColin Finck     RegCloseKey(netsetup);
579c42b133eSAmine Khaldi     return filename;
580c2c66affSColin Finck }
581c2c66affSColin Finck 
582*f4be6dc3SMikhail struct lang_codepage
583c2c66affSColin Finck {
584c2c66affSColin Finck   WORD wLanguage;
585c2c66affSColin Finck   WORD wCodePage;
586*f4be6dc3SMikhail };
587c2c66affSColin Finck 
set_msi_assembly_prop(MSIPACKAGE * package)588c2c66affSColin Finck static void set_msi_assembly_prop(MSIPACKAGE *package)
589c2c66affSColin Finck {
590c2c66affSColin Finck     UINT val_len;
591c2c66affSColin Finck     DWORD size, handle;
592c2c66affSColin Finck     LPVOID version = NULL;
593c2c66affSColin Finck     WCHAR buf[MAX_PATH];
594c2c66affSColin Finck     LPWSTR fusion, verstr;
595*f4be6dc3SMikhail     struct lang_codepage *translate;
596c2c66affSColin Finck 
597c2c66affSColin Finck     fusion = get_fusion_filename(package);
598c2c66affSColin Finck     if (!fusion)
599c2c66affSColin Finck         return;
600c2c66affSColin Finck 
601c2c66affSColin Finck     size = GetFileVersionInfoSizeW(fusion, &handle);
602c2c66affSColin Finck     if (!size)
603c2c66affSColin Finck         goto done;
604c2c66affSColin Finck 
605*f4be6dc3SMikhail     version = malloc(size);
606c2c66affSColin Finck     if (!version)
607c2c66affSColin Finck         goto done;
608c2c66affSColin Finck 
609c2c66affSColin Finck     if (!GetFileVersionInfoW(fusion, handle, size, version))
610c2c66affSColin Finck         goto done;
611c2c66affSColin Finck 
6120272139cSwinesync     if (!VerQueryValueW(version, L"\\VarFileInfo\\Translation", (LPVOID *)&translate, &val_len))
613c2c66affSColin Finck         goto done;
614c2c66affSColin Finck 
6150272139cSwinesync     swprintf(buf, ARRAY_SIZE(buf), L"\\StringFileInfo\\%04x%04x\\ProductVersion", translate[0].wLanguage,
6160272139cSwinesync              translate[0].wCodePage);
617c2c66affSColin Finck 
618c2c66affSColin Finck     if (!VerQueryValueW(version, buf, (LPVOID *)&verstr, &val_len))
619c2c66affSColin Finck         goto done;
620c2c66affSColin Finck 
621c2c66affSColin Finck     if (!val_len || !verstr)
622c2c66affSColin Finck         goto done;
623c2c66affSColin Finck 
6240272139cSwinesync     msi_set_property( package->db, L"MsiNetAssemblySupport", verstr, -1 );
625c2c66affSColin Finck 
626c2c66affSColin Finck done:
627*f4be6dc3SMikhail     free(fusion);
628*f4be6dc3SMikhail     free(version);
629c2c66affSColin Finck }
630c2c66affSColin Finck 
set_installer_properties(MSIPACKAGE * package)631c2c66affSColin Finck static VOID set_installer_properties(MSIPACKAGE *package)
632c2c66affSColin Finck {
633c2c66affSColin Finck     WCHAR *ptr;
634f4d2571bSwinesync     RTL_OSVERSIONINFOEXW OSVersion;
635c2c66affSColin Finck     MEMORYSTATUSEX msex;
6363ec0ea99Swinesync     DWORD verval, len, type;
637c2c66affSColin Finck     WCHAR pth[MAX_PATH], verstr[11], bufstr[22];
638c2c66affSColin Finck     HDC dc;
639c2c66affSColin Finck     HKEY hkey;
640c2c66affSColin Finck     LPWSTR username, companyname;
641c2c66affSColin Finck     SYSTEM_INFO sys_info;
642c2c66affSColin Finck     LANGID langid;
643c2c66affSColin Finck 
644c2c66affSColin Finck     /*
645c2c66affSColin Finck      * Other things that probably should be set:
646c2c66affSColin Finck      *
647c2c66affSColin Finck      * VirtualMemory ShellAdvSupport DefaultUIFont PackagecodeChanging
648c2c66affSColin Finck      * CaptionHeight BorderTop BorderSide TextHeight RedirectedDllSupport
649c2c66affSColin Finck      */
650c2c66affSColin Finck 
651c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, 0, pth);
6520272139cSwinesync     lstrcatW(pth, L"\\");
6530272139cSwinesync     msi_set_property( package->db, L"CommonAppDataFolder", pth, -1 );
654c2c66affSColin Finck 
655c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_FAVORITES, NULL, 0, pth);
6560272139cSwinesync     lstrcatW(pth, L"\\");
6570272139cSwinesync     msi_set_property( package->db, L"FavoritesFolder", pth, -1 );
658c2c66affSColin Finck 
659c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_FONTS, NULL, 0, pth);
6600272139cSwinesync     lstrcatW(pth, L"\\");
6610272139cSwinesync     msi_set_property( package->db, L"FontsFolder", pth, -1 );
662c2c66affSColin Finck 
663c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_SENDTO, NULL, 0, pth);
6640272139cSwinesync     lstrcatW(pth, L"\\");
6650272139cSwinesync     msi_set_property( package->db, L"SendToFolder", pth, -1 );
666c2c66affSColin Finck 
667c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_STARTMENU, NULL, 0, pth);
6680272139cSwinesync     lstrcatW(pth, L"\\");
6690272139cSwinesync     msi_set_property( package->db, L"StartMenuFolder", pth, -1 );
670c2c66affSColin Finck 
671c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_STARTUP, NULL, 0, pth);
6720272139cSwinesync     lstrcatW(pth, L"\\");
6730272139cSwinesync     msi_set_property( package->db, L"StartupFolder", pth, -1 );
674c2c66affSColin Finck 
675c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_TEMPLATES, NULL, 0, pth);
6760272139cSwinesync     lstrcatW(pth, L"\\");
6770272139cSwinesync     msi_set_property( package->db, L"TemplateFolder", pth, -1 );
678c2c66affSColin Finck 
679c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, pth);
6800272139cSwinesync     lstrcatW(pth, L"\\");
6810272139cSwinesync     msi_set_property( package->db, L"DesktopFolder", pth, -1 );
682c2c66affSColin Finck 
683c2c66affSColin Finck     /* FIXME: set to AllUsers profile path if ALLUSERS is set */
684c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_PROGRAMS, NULL, 0, pth);
6850272139cSwinesync     lstrcatW(pth, L"\\");
6860272139cSwinesync     msi_set_property( package->db, L"ProgramMenuFolder", pth, -1 );
687c2c66affSColin Finck 
688c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_ADMINTOOLS, NULL, 0, pth);
6890272139cSwinesync     lstrcatW(pth, L"\\");
6900272139cSwinesync     msi_set_property( package->db, L"AdminToolsFolder", pth, -1 );
691c2c66affSColin Finck 
692c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, pth);
6930272139cSwinesync     lstrcatW(pth, L"\\");
6940272139cSwinesync     msi_set_property( package->db, L"AppDataFolder", pth, -1 );
695c2c66affSColin Finck 
696c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_SYSTEM, NULL, 0, pth);
6970272139cSwinesync     lstrcatW(pth, L"\\");
6980272139cSwinesync     msi_set_property( package->db, L"SystemFolder", pth, -1 );
6990272139cSwinesync     msi_set_property( package->db, L"System16Folder", pth, -1 );
700c2c66affSColin Finck 
701c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, pth);
7020272139cSwinesync     lstrcatW(pth, L"\\");
7030272139cSwinesync     msi_set_property( package->db, L"LocalAppDataFolder", pth, -1 );
704c2c66affSColin Finck 
705c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_MYPICTURES, NULL, 0, pth);
7060272139cSwinesync     lstrcatW(pth, L"\\");
7070272139cSwinesync     msi_set_property( package->db, L"MyPicturesFolder", pth, -1 );
708c2c66affSColin Finck 
709c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, 0, pth);
7100272139cSwinesync     lstrcatW(pth, L"\\");
7110272139cSwinesync     msi_set_property( package->db, L"PersonalFolder", pth, -1 );
712c2c66affSColin Finck 
713c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth);
7140272139cSwinesync     lstrcatW(pth, L"\\");
7150272139cSwinesync     msi_set_property( package->db, L"WindowsFolder", pth, -1 );
716c2c66affSColin Finck 
717c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_PRINTHOOD, NULL, 0, pth);
7180272139cSwinesync     lstrcatW(pth, L"\\");
7190272139cSwinesync     msi_set_property( package->db, L"PrintHoodFolder", pth, -1 );
720c2c66affSColin Finck 
721c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_NETHOOD, NULL, 0, pth);
7220272139cSwinesync     lstrcatW(pth, L"\\");
7230272139cSwinesync     msi_set_property( package->db, L"NetHoodFolder", pth, -1 );
724c2c66affSColin Finck 
725c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_RECENT, NULL, 0, pth);
7260272139cSwinesync     lstrcatW(pth, L"\\");
7270272139cSwinesync     msi_set_property( package->db, L"RecentFolder", pth, -1 );
728c2c66affSColin Finck 
729c2c66affSColin Finck     /* Physical Memory is specified in MB. Using total amount. */
730c2c66affSColin Finck     msex.dwLength = sizeof(msex);
731c2c66affSColin Finck     GlobalMemoryStatusEx( &msex );
7320272139cSwinesync     len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", (int)(msex.ullTotalPhys / 1024 / 1024) );
7330272139cSwinesync     msi_set_property( package->db, L"PhysicalMemory", bufstr, len );
734c2c66affSColin Finck 
735c2c66affSColin Finck     SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth);
736958f1addSwinesync     ptr = wcschr(pth,'\\');
737c2c66affSColin Finck     if (ptr) *(ptr + 1) = 0;
7380272139cSwinesync     msi_set_property( package->db, L"WindowsVolume", pth, -1 );
739c2c66affSColin Finck 
740c2c66affSColin Finck     len = GetTempPathW(MAX_PATH, pth);
7410272139cSwinesync     msi_set_property( package->db, L"TempFolder", pth, len );
742c2c66affSColin Finck 
743c2c66affSColin Finck     /* in a wine environment the user is always admin and privileged */
7440272139cSwinesync     msi_set_property( package->db, L"AdminUser", L"1", -1 );
7450272139cSwinesync     msi_set_property( package->db, L"Privileged", L"1", -1 );
74685854456Swinesync     msi_set_property( package->db, L"MsiRunningElevated", L"1", -1 );
747c2c66affSColin Finck 
748c2c66affSColin Finck     /* set the os things */
749f4d2571bSwinesync     OSVersion.dwOSVersionInfoSize = sizeof(OSVersion);
750f4d2571bSwinesync     RtlGetVersion((PRTL_OSVERSIONINFOW)&OSVersion);
751c2c66affSColin Finck     verval = OSVersion.dwMinorVersion + OSVersion.dwMajorVersion * 100;
752f4d2571bSwinesync     if (verval > 603)
753f4d2571bSwinesync     {
754f4d2571bSwinesync         verval = 603;
755f4d2571bSwinesync         OSVersion.dwBuildNumber = 9600;
756f4d2571bSwinesync     }
7570272139cSwinesync     len = swprintf( verstr, ARRAY_SIZE(verstr), L"%u", verval );
758c2c66affSColin Finck     switch (OSVersion.dwPlatformId)
759c2c66affSColin Finck     {
760c2c66affSColin Finck         case VER_PLATFORM_WIN32_WINDOWS:
7610272139cSwinesync             msi_set_property( package->db, L"Version9X", verstr, len );
762c2c66affSColin Finck             break;
763c2c66affSColin Finck         case VER_PLATFORM_WIN32_NT:
7640272139cSwinesync             msi_set_property( package->db, L"VersionNT", verstr, len );
7650272139cSwinesync             len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%u", OSVersion.wProductType );
7660272139cSwinesync             msi_set_property( package->db, L"MsiNTProductType", bufstr, len );
767c2c66affSColin Finck             break;
768c2c66affSColin Finck     }
7690272139cSwinesync     len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%u", OSVersion.dwBuildNumber );
7700272139cSwinesync     msi_set_property( package->db, L"WindowsBuild", bufstr, len );
7710272139cSwinesync     len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%u", OSVersion.wServicePackMajor );
7720272139cSwinesync     msi_set_property( package->db, L"ServicePackLevel", bufstr, len );
773c2c66affSColin Finck 
7740272139cSwinesync     len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%u.%u", MSI_MAJORVERSION, MSI_MINORVERSION );
7750272139cSwinesync     msi_set_property( package->db, L"VersionMsi", bufstr, len );
7760272139cSwinesync     len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%u", MSI_MAJORVERSION * 100 );
7770272139cSwinesync     msi_set_property( package->db, L"VersionDatabase", bufstr, len );
778c2c66affSColin Finck 
7790272139cSwinesync     RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion", 0,
7803ec0ea99Swinesync         KEY_QUERY_VALUE | KEY_WOW64_64KEY, &hkey);
7813ec0ea99Swinesync 
782c2c66affSColin Finck     GetNativeSystemInfo( &sys_info );
7830272139cSwinesync     len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", sys_info.wProcessorLevel );
7840272139cSwinesync     msi_set_property( package->db, L"Intel", bufstr, len );
785*f4be6dc3SMikhail     if (sys_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
786c2c66affSColin Finck     {
787c2c66affSColin Finck         GetSystemDirectoryW( pth, MAX_PATH );
788c2c66affSColin Finck         PathAddBackslashW( pth );
7890272139cSwinesync         msi_set_property( package->db, L"SystemFolder", pth, -1 );
790c2c66affSColin Finck 
7918c1eae24Swinesync         len = sizeof(pth);
7920272139cSwinesync         RegQueryValueExW(hkey, L"ProgramFilesDir", 0, &type, (BYTE *)pth, &len);
793c2c66affSColin Finck         PathAddBackslashW( pth );
7940272139cSwinesync         msi_set_property( package->db, L"ProgramFilesFolder", pth, -1 );
795c2c66affSColin Finck 
7968c1eae24Swinesync         len = sizeof(pth);
7970272139cSwinesync         RegQueryValueExW(hkey, L"CommonFilesDir", 0, &type, (BYTE *)pth, &len);
798c2c66affSColin Finck         PathAddBackslashW( pth );
7990272139cSwinesync         msi_set_property( package->db, L"CommonFilesFolder", pth, -1 );
800c2c66affSColin Finck     }
801*f4be6dc3SMikhail     else if (sys_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
802c2c66affSColin Finck     {
8030272139cSwinesync         msi_set_property( package->db, L"MsiAMD64", bufstr, -1 );
8040272139cSwinesync         msi_set_property( package->db, L"Msix64", bufstr, -1 );
8050272139cSwinesync         msi_set_property( package->db, L"VersionNT64", verstr, -1 );
806c2c66affSColin Finck 
807c2c66affSColin Finck         GetSystemDirectoryW( pth, MAX_PATH );
808c2c66affSColin Finck         PathAddBackslashW( pth );
8090272139cSwinesync         msi_set_property( package->db, L"System64Folder", pth, -1 );
810c2c66affSColin Finck 
811c2c66affSColin Finck         GetSystemWow64DirectoryW( pth, MAX_PATH );
812c2c66affSColin Finck         PathAddBackslashW( pth );
8130272139cSwinesync         msi_set_property( package->db, L"SystemFolder", pth, -1 );
814c2c66affSColin Finck 
8158c1eae24Swinesync         len = sizeof(pth);
8160272139cSwinesync         RegQueryValueExW(hkey, L"ProgramFilesDir", 0, &type, (BYTE *)pth, &len);
817c2c66affSColin Finck         PathAddBackslashW( pth );
8180272139cSwinesync         msi_set_property( package->db, L"ProgramFiles64Folder", pth, -1 );
819c2c66affSColin Finck 
8208c1eae24Swinesync         len = sizeof(pth);
8210272139cSwinesync         RegQueryValueExW(hkey, L"ProgramFilesDir (x86)", 0, &type, (BYTE *)pth, &len);
822c2c66affSColin Finck         PathAddBackslashW( pth );
8230272139cSwinesync         msi_set_property( package->db, L"ProgramFilesFolder", pth, -1 );
824c2c66affSColin Finck 
8258c1eae24Swinesync         len = sizeof(pth);
8260272139cSwinesync         RegQueryValueExW(hkey, L"CommonFilesDir", 0, &type, (BYTE *)pth, &len);
827c2c66affSColin Finck         PathAddBackslashW( pth );
8280272139cSwinesync         msi_set_property( package->db, L"CommonFiles64Folder", pth, -1 );
829c2c66affSColin Finck 
8308c1eae24Swinesync         len = sizeof(pth);
8310272139cSwinesync         RegQueryValueExW(hkey, L"CommonFilesDir (x86)", 0, &type, (BYTE *)pth, &len);
832c2c66affSColin Finck         PathAddBackslashW( pth );
8330272139cSwinesync         msi_set_property( package->db, L"CommonFilesFolder", pth, -1 );
834c2c66affSColin Finck     }
835c2c66affSColin Finck 
8363ec0ea99Swinesync     RegCloseKey(hkey);
8373ec0ea99Swinesync 
838c2c66affSColin Finck     /* Screen properties. */
839c2c66affSColin Finck     dc = GetDC(0);
8400272139cSwinesync     len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", GetDeviceCaps(dc, HORZRES) );
8410272139cSwinesync     msi_set_property( package->db, L"ScreenX", bufstr, len );
8420272139cSwinesync     len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", GetDeviceCaps(dc, VERTRES) );
8430272139cSwinesync     msi_set_property( package->db, L"ScreenY", bufstr, len );
8440272139cSwinesync     len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", GetDeviceCaps(dc, BITSPIXEL) );
8450272139cSwinesync     msi_set_property( package->db, L"ColorBits", bufstr, len );
846c2c66affSColin Finck     ReleaseDC(0, dc);
847c2c66affSColin Finck 
848c2c66affSColin Finck     /* USERNAME and COMPANYNAME */
8490272139cSwinesync     username = msi_dup_property( package->db, L"USERNAME" );
8500272139cSwinesync     companyname = msi_dup_property( package->db, L"COMPANYNAME" );
851c2c66affSColin Finck 
852c2c66affSColin Finck     if ((!username || !companyname) &&
8530272139cSwinesync         RegOpenKeyW( HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\MS Setup (ACME)\\User Info", &hkey ) == ERROR_SUCCESS)
854c2c66affSColin Finck     {
855c2c66affSColin Finck         if (!username &&
8560272139cSwinesync             (username = msi_reg_get_val_str( hkey, L"DefName" )))
8570272139cSwinesync             msi_set_property( package->db, L"USERNAME", username, -1 );
858c2c66affSColin Finck         if (!companyname &&
8590272139cSwinesync             (companyname = msi_reg_get_val_str( hkey, L"DefCompany" )))
8600272139cSwinesync             msi_set_property( package->db, L"COMPANYNAME", companyname, -1 );
861c2c66affSColin Finck         CloseHandle( hkey );
862c2c66affSColin Finck     }
863c2c66affSColin Finck     if ((!username || !companyname) &&
8640272139cSwinesync         RegOpenKeyExW( HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0,
8650272139cSwinesync                        KEY_QUERY_VALUE|KEY_WOW64_64KEY, &hkey ) == ERROR_SUCCESS)
866c2c66affSColin Finck     {
867c2c66affSColin Finck         if (!username &&
8680272139cSwinesync             (username = msi_reg_get_val_str( hkey, L"RegisteredOwner" )))
8690272139cSwinesync             msi_set_property( package->db, L"USERNAME", username, -1 );
870c2c66affSColin Finck         if (!companyname &&
8710272139cSwinesync             (companyname = msi_reg_get_val_str( hkey, L"RegisteredOrganization" )))
8720272139cSwinesync             msi_set_property( package->db, L"COMPANYNAME", companyname, -1 );
873c2c66affSColin Finck         CloseHandle( hkey );
874c2c66affSColin Finck     }
875*f4be6dc3SMikhail     free( username );
876*f4be6dc3SMikhail     free( companyname );
877c2c66affSColin Finck 
878c2c66affSColin Finck     if ( set_user_sid_prop( package ) != ERROR_SUCCESS)
879c2c66affSColin Finck         ERR("Failed to set the UserSID property\n");
880c2c66affSColin Finck 
881c2c66affSColin Finck     set_msi_assembly_prop( package );
882c2c66affSColin Finck 
883c2c66affSColin Finck     langid = GetUserDefaultLangID();
8840272139cSwinesync     len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", langid );
8850272139cSwinesync     msi_set_property( package->db, L"UserLanguageID", bufstr, len );
886c2c66affSColin Finck 
887c2c66affSColin Finck     langid = GetSystemDefaultLangID();
8880272139cSwinesync     len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", langid );
8890272139cSwinesync     msi_set_property( package->db, L"SystemLanguageID", bufstr, len );
890c2c66affSColin Finck 
8910272139cSwinesync     len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", MsiQueryProductStateW(package->ProductCode) );
8920272139cSwinesync     msi_set_property( package->db, L"ProductState", bufstr, len );
893c2c66affSColin Finck 
894c2c66affSColin Finck     len = 0;
895c2c66affSColin Finck     if (!GetUserNameW( NULL, &len ) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
896c2c66affSColin Finck     {
897c2c66affSColin Finck         WCHAR *username;
898*f4be6dc3SMikhail         if ((username = malloc( len * sizeof(WCHAR) )))
899c2c66affSColin Finck         {
900c2c66affSColin Finck             if (GetUserNameW( username, &len ))
9010272139cSwinesync                 msi_set_property( package->db, L"LogonUser", username, len - 1 );
902*f4be6dc3SMikhail             free( username );
903c2c66affSColin Finck         }
904c2c66affSColin Finck     }
905c2c66affSColin Finck     len = 0;
906c2c66affSColin Finck     if (!GetComputerNameW( NULL, &len ) && GetLastError() == ERROR_BUFFER_OVERFLOW)
907c2c66affSColin Finck     {
908c2c66affSColin Finck         WCHAR *computername;
909*f4be6dc3SMikhail         if ((computername = malloc( len * sizeof(WCHAR) )))
910c2c66affSColin Finck         {
911c2c66affSColin Finck             if (GetComputerNameW( computername, &len ))
9120272139cSwinesync                 msi_set_property( package->db, L"ComputerName", computername, len );
913*f4be6dc3SMikhail             free( computername );
914c2c66affSColin Finck         }
915c2c66affSColin Finck     }
916c2c66affSColin Finck }
917c2c66affSColin Finck 
alloc_package(void)918*f4be6dc3SMikhail static MSIPACKAGE *alloc_package( void )
919c2c66affSColin Finck {
920c2c66affSColin Finck     MSIPACKAGE *package;
921c2c66affSColin Finck 
922c2c66affSColin Finck     package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE),
923c2c66affSColin Finck                                MSI_FreePackage );
924c2c66affSColin Finck     if( package )
925c2c66affSColin Finck     {
926c2c66affSColin Finck         list_init( &package->components );
927c2c66affSColin Finck         list_init( &package->features );
928c2c66affSColin Finck         list_init( &package->files );
929c2c66affSColin Finck         list_init( &package->filepatches );
930c2c66affSColin Finck         list_init( &package->tempfiles );
931c2c66affSColin Finck         list_init( &package->folders );
932c2c66affSColin Finck         list_init( &package->subscriptions );
933c2c66affSColin Finck         list_init( &package->appids );
934c2c66affSColin Finck         list_init( &package->classes );
935c2c66affSColin Finck         list_init( &package->mimes );
936c2c66affSColin Finck         list_init( &package->extensions );
937c2c66affSColin Finck         list_init( &package->progids );
938c2c66affSColin Finck         list_init( &package->RunningActions );
939c2c66affSColin Finck         list_init( &package->sourcelist_info );
940c2c66affSColin Finck         list_init( &package->sourcelist_media );
941c2c66affSColin Finck         list_init( &package->patches );
942c2c66affSColin Finck         list_init( &package->binaries );
943c2c66affSColin Finck         list_init( &package->cabinet_streams );
944c2c66affSColin Finck     }
945c2c66affSColin Finck 
946c2c66affSColin Finck     return package;
947c2c66affSColin Finck }
948c2c66affSColin Finck 
load_admin_properties(MSIPACKAGE * package)949*f4be6dc3SMikhail static UINT load_admin_properties(MSIPACKAGE *package)
950c2c66affSColin Finck {
951c2c66affSColin Finck     BYTE *data;
952c2c66affSColin Finck     UINT r, sz;
953c2c66affSColin Finck 
9540272139cSwinesync     r = read_stream_data(package->db->storage, L"AdminProperties", FALSE, &data, &sz);
955c2c66affSColin Finck     if (r != ERROR_SUCCESS)
956c2c66affSColin Finck         return r;
957c2c66affSColin Finck 
958c2c66affSColin Finck     r = msi_parse_command_line(package, (WCHAR *)data, TRUE);
959c2c66affSColin Finck 
960*f4be6dc3SMikhail     free(data);
961c2c66affSColin Finck     return r;
962c2c66affSColin Finck }
963c2c66affSColin Finck 
msi_adjust_privilege_properties(MSIPACKAGE * package)964c2c66affSColin Finck void msi_adjust_privilege_properties( MSIPACKAGE *package )
965c2c66affSColin Finck {
966c2c66affSColin Finck     /* FIXME: this should depend on the user's privileges */
9670272139cSwinesync     if (msi_get_property_int( package->db, L"ALLUSERS", 0 ) == 2)
968c2c66affSColin Finck     {
969c2c66affSColin Finck         TRACE("resetting ALLUSERS property from 2 to 1\n");
9700272139cSwinesync         msi_set_property( package->db, L"ALLUSERS", L"1", -1 );
971c2c66affSColin Finck     }
9720272139cSwinesync     msi_set_property( package->db, L"AdminUser", L"1", -1 );
97385854456Swinesync     msi_set_property( package->db, L"Privileged", L"1", -1 );
97485854456Swinesync     msi_set_property( package->db, L"MsiRunningElevated", L"1", -1 );
975c2c66affSColin Finck }
976c2c66affSColin Finck 
MSI_CreatePackage(MSIDATABASE * db)97734c2011cSwinesync MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db )
978c2c66affSColin Finck {
979c2c66affSColin Finck     MSIPACKAGE *package;
980c2c66affSColin Finck     WCHAR uilevel[11];
981c2c66affSColin Finck     int len;
982c2c66affSColin Finck     UINT r;
983c2c66affSColin Finck 
984c2c66affSColin Finck     TRACE("%p\n", db);
985c2c66affSColin Finck 
986*f4be6dc3SMikhail     package = alloc_package();
987c2c66affSColin Finck     if (package)
988c2c66affSColin Finck     {
989c2c66affSColin Finck         msiobj_addref( &db->hdr );
990c2c66affSColin Finck         package->db = db;
991c2c66affSColin Finck 
99271bffdcdSAmine Khaldi         package->LastAction = NULL;
99371bffdcdSAmine Khaldi         package->LastActionTemplate = NULL;
99471bffdcdSAmine Khaldi         package->LastActionResult = MSI_NULL_INTEGER;
995c2c66affSColin Finck         package->WordCount = 0;
996*f4be6dc3SMikhail         package->PackagePath = wcsdup( db->path );
997c2c66affSColin Finck 
998c2c66affSColin Finck         create_temp_property_table( package );
999c2c66affSColin Finck         msi_clone_properties( package->db );
1000c2c66affSColin Finck         msi_adjust_privilege_properties( package );
1001c2c66affSColin Finck 
10020272139cSwinesync         package->ProductCode = msi_dup_property( package->db, L"ProductCode" );
1003c2c66affSColin Finck 
1004c2c66affSColin Finck         set_installer_properties( package );
1005c2c66affSColin Finck 
1006c2c66affSColin Finck         package->ui_level = gUILevel;
10070272139cSwinesync         len = swprintf( uilevel, ARRAY_SIZE(uilevel), L"%u", gUILevel & INSTALLUILEVEL_MASK );
10080272139cSwinesync         msi_set_property( package->db, L"UILevel", uilevel, len );
1009c2c66affSColin Finck 
1010c2c66affSColin Finck         r = msi_load_suminfo_properties( package );
1011c2c66affSColin Finck         if (r != ERROR_SUCCESS)
1012c2c66affSColin Finck         {
1013c2c66affSColin Finck             msiobj_release( &package->hdr );
1014c2c66affSColin Finck             return NULL;
1015c2c66affSColin Finck         }
1016c2c66affSColin Finck 
1017c2c66affSColin Finck         if (package->WordCount & msidbSumInfoSourceTypeAdminImage)
1018*f4be6dc3SMikhail             load_admin_properties( package );
1019c2c66affSColin Finck 
1020c2c66affSColin Finck         package->log_file = INVALID_HANDLE_VALUE;
10210d762dcbSwinesync         package->script = SCRIPT_NONE;
1022c2c66affSColin Finck     }
1023c2c66affSColin Finck     return package;
1024c2c66affSColin Finck }
1025c2c66affSColin Finck 
msi_download_file(LPCWSTR szUrl,LPWSTR filename)1026c2c66affSColin Finck UINT msi_download_file( LPCWSTR szUrl, LPWSTR filename )
1027c2c66affSColin Finck {
1028c2c66affSColin Finck     LPINTERNET_CACHE_ENTRY_INFOW cache_entry;
1029c2c66affSColin Finck     DWORD size = 0;
1030c2c66affSColin Finck     HRESULT hr;
1031c2c66affSColin Finck 
1032c2c66affSColin Finck     /* call will always fail, because size is 0,
1033c2c66affSColin Finck      * but will return ERROR_FILE_NOT_FOUND first
1034c2c66affSColin Finck      * if the file doesn't exist
1035c2c66affSColin Finck      */
1036c2c66affSColin Finck     GetUrlCacheEntryInfoW( szUrl, NULL, &size );
1037c2c66affSColin Finck     if ( GetLastError() != ERROR_FILE_NOT_FOUND )
1038c2c66affSColin Finck     {
1039*f4be6dc3SMikhail         cache_entry = malloc( size );
1040c2c66affSColin Finck         if ( !GetUrlCacheEntryInfoW( szUrl, cache_entry, &size ) )
1041c2c66affSColin Finck         {
1042c2c66affSColin Finck             UINT error = GetLastError();
1043*f4be6dc3SMikhail             free( cache_entry );
1044c2c66affSColin Finck             return error;
1045c2c66affSColin Finck         }
1046c2c66affSColin Finck 
1047c2c66affSColin Finck         lstrcpyW( filename, cache_entry->lpszLocalFileName );
1048*f4be6dc3SMikhail         free( cache_entry );
1049c2c66affSColin Finck         return ERROR_SUCCESS;
1050c2c66affSColin Finck     }
1051c2c66affSColin Finck 
1052c2c66affSColin Finck     hr = URLDownloadToCacheFileW( NULL, szUrl, filename, MAX_PATH, 0, NULL );
1053c2c66affSColin Finck     if ( FAILED(hr) )
1054c2c66affSColin Finck     {
1055c2c66affSColin Finck         WARN("failed to download %s to cache file\n", debugstr_w(szUrl));
1056c2c66affSColin Finck         return ERROR_FUNCTION_FAILED;
1057c2c66affSColin Finck     }
1058c2c66affSColin Finck 
1059c2c66affSColin Finck     return ERROR_SUCCESS;
1060c2c66affSColin Finck }
1061c2c66affSColin Finck 
msi_create_empty_local_file(LPWSTR path,LPCWSTR suffix)1062c2c66affSColin Finck UINT msi_create_empty_local_file( LPWSTR path, LPCWSTR suffix )
1063c2c66affSColin Finck {
1064c2c66affSColin Finck     DWORD time, len, i, offset;
1065c2c66affSColin Finck     HANDLE handle;
1066c2c66affSColin Finck 
1067c2c66affSColin Finck     time = GetTickCount();
1068c2c66affSColin Finck     GetWindowsDirectoryW( path, MAX_PATH );
10690272139cSwinesync     lstrcatW( path, L"\\Installer\\" );
1070c2c66affSColin Finck     CreateDirectoryW( path, NULL );
1071c2c66affSColin Finck 
1072958f1addSwinesync     len = lstrlenW(path);
1073c2c66affSColin Finck     for (i = 0; i < 0x10000; i++)
1074c2c66affSColin Finck     {
10750272139cSwinesync         offset = swprintf( path + len, MAX_PATH - len, L"%x", (time + i) & 0xffff );
1076958f1addSwinesync         memcpy( path + len + offset, suffix, (lstrlenW( suffix ) + 1) * sizeof(WCHAR) );
1077c2c66affSColin Finck         handle = CreateFileW( path, GENERIC_WRITE, 0, NULL,
1078c2c66affSColin Finck                               CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
1079c2c66affSColin Finck         if (handle != INVALID_HANDLE_VALUE)
1080c2c66affSColin Finck         {
1081c2c66affSColin Finck             CloseHandle(handle);
1082c2c66affSColin Finck             break;
1083c2c66affSColin Finck         }
1084c2c66affSColin Finck         if (GetLastError() != ERROR_FILE_EXISTS &&
1085c2c66affSColin Finck             GetLastError() != ERROR_SHARING_VIOLATION)
1086c2c66affSColin Finck             return ERROR_FUNCTION_FAILED;
1087c2c66affSColin Finck     }
1088c2c66affSColin Finck 
1089c2c66affSColin Finck     return ERROR_SUCCESS;
1090c2c66affSColin Finck }
1091c2c66affSColin Finck 
parse_platform(const WCHAR * str)1092c2c66affSColin Finck static enum platform parse_platform( const WCHAR *str )
1093c2c66affSColin Finck {
10940272139cSwinesync     if (!str[0] || !wcscmp( str, L"Intel" )) return PLATFORM_INTEL;
10950272139cSwinesync     else if (!wcscmp( str, L"Intel64" )) return PLATFORM_INTEL64;
10960272139cSwinesync     else if (!wcscmp( str, L"x64" ) || !wcscmp( str, L"AMD64" )) return PLATFORM_X64;
10970272139cSwinesync     else if (!wcscmp( str, L"Arm" )) return PLATFORM_ARM;
10980272139cSwinesync     else if (!wcscmp( str, L"Arm64" )) return PLATFORM_ARM64;
109998d8ddaaSwinesync     return PLATFORM_UNRECOGNIZED;
1100c2c66affSColin Finck }
1101c2c66affSColin Finck 
parse_suminfo(MSISUMMARYINFO * si,MSIPACKAGE * package)1102c2c66affSColin Finck static UINT parse_suminfo( MSISUMMARYINFO *si, MSIPACKAGE *package )
1103c2c66affSColin Finck {
1104c2c66affSColin Finck     WCHAR *template, *p, *q, *platform;
1105c2c66affSColin Finck     DWORD i, count;
1106c2c66affSColin Finck 
1107c2c66affSColin Finck     package->version = msi_suminfo_get_int32( si, PID_PAGECOUNT );
1108c2c66affSColin Finck     TRACE("version: %d\n", package->version);
1109c2c66affSColin Finck 
1110c2c66affSColin Finck     template = msi_suminfo_dup_string( si, PID_TEMPLATE );
1111c2c66affSColin Finck     if (!template)
1112c2c66affSColin Finck         return ERROR_SUCCESS; /* native accepts missing template property */
1113c2c66affSColin Finck 
1114c2c66affSColin Finck     TRACE("template: %s\n", debugstr_w(template));
1115c2c66affSColin Finck 
1116958f1addSwinesync     p = wcschr( template, ';' );
1117c2c66affSColin Finck     if (!p)
1118c2c66affSColin Finck     {
1119c2c66affSColin Finck         WARN("invalid template string %s\n", debugstr_w(template));
1120*f4be6dc3SMikhail         free( template );
1121c2c66affSColin Finck         return ERROR_PATCH_PACKAGE_INVALID;
1122c2c66affSColin Finck     }
1123c2c66affSColin Finck     *p = 0;
1124c2c66affSColin Finck     platform = template;
1125958f1addSwinesync     if ((q = wcschr( platform, ',' ))) *q = 0;
1126c2c66affSColin Finck     package->platform = parse_platform( platform );
112798d8ddaaSwinesync     while (package->platform == PLATFORM_UNRECOGNIZED && q)
1128c2c66affSColin Finck     {
1129c2c66affSColin Finck         platform = q + 1;
1130958f1addSwinesync         if ((q = wcschr( platform, ',' ))) *q = 0;
1131c2c66affSColin Finck         package->platform = parse_platform( platform );
1132c2c66affSColin Finck     }
113398d8ddaaSwinesync     if (package->platform == PLATFORM_UNRECOGNIZED)
1134c2c66affSColin Finck     {
1135c2c66affSColin Finck         WARN("unknown platform %s\n", debugstr_w(template));
1136*f4be6dc3SMikhail         free( template );
1137c2c66affSColin Finck         return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
1138c2c66affSColin Finck     }
1139c2c66affSColin Finck     p++;
1140c2c66affSColin Finck     if (!*p)
1141c2c66affSColin Finck     {
1142*f4be6dc3SMikhail         free( template );
1143c2c66affSColin Finck         return ERROR_SUCCESS;
1144c2c66affSColin Finck     }
1145c2c66affSColin Finck     count = 1;
1146958f1addSwinesync     for (q = p; (q = wcschr( q, ',' )); q++) count++;
1147c2c66affSColin Finck 
1148*f4be6dc3SMikhail     package->langids = malloc( count * sizeof(LANGID) );
1149c2c66affSColin Finck     if (!package->langids)
1150c2c66affSColin Finck     {
1151*f4be6dc3SMikhail         free( template );
1152c2c66affSColin Finck         return ERROR_OUTOFMEMORY;
1153c2c66affSColin Finck     }
1154c2c66affSColin Finck 
1155c2c66affSColin Finck     i = 0;
1156c2c66affSColin Finck     while (*p)
1157c2c66affSColin Finck     {
1158958f1addSwinesync         q = wcschr( p, ',' );
1159c2c66affSColin Finck         if (q) *q = 0;
1160958f1addSwinesync         package->langids[i] = wcstol( p, NULL, 10 );
1161c2c66affSColin Finck         if (!q) break;
1162c2c66affSColin Finck         p = q + 1;
1163c2c66affSColin Finck         i++;
1164c2c66affSColin Finck     }
1165c2c66affSColin Finck     package->num_langids = i + 1;
1166c2c66affSColin Finck 
1167*f4be6dc3SMikhail     free( template );
1168c2c66affSColin Finck     return ERROR_SUCCESS;
1169c2c66affSColin Finck }
1170c2c66affSColin Finck 
validate_package(MSIPACKAGE * package)1171c2c66affSColin Finck static UINT validate_package( MSIPACKAGE *package )
1172c2c66affSColin Finck {
1173c2c66affSColin Finck     UINT i;
1174c2c66affSColin Finck 
1175c2c66affSColin Finck     if (package->platform == PLATFORM_INTEL64)
1176c2c66affSColin Finck         return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
1177c2c66affSColin Finck #ifndef __arm__
1178c2c66affSColin Finck     if (package->platform == PLATFORM_ARM)
1179c2c66affSColin Finck         return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
1180c2c66affSColin Finck #endif
1181de59794fSwinesync #ifndef __aarch64__
1182de59794fSwinesync     if (package->platform == PLATFORM_ARM64)
1183de59794fSwinesync         return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
1184de59794fSwinesync #endif
1185c2c66affSColin Finck     if (package->platform == PLATFORM_X64)
1186c2c66affSColin Finck     {
1187c2c66affSColin Finck         if (!is_64bit && !is_wow64)
1188c2c66affSColin Finck             return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
1189c2c66affSColin Finck         if (package->version < 200)
1190c2c66affSColin Finck             return ERROR_INSTALL_PACKAGE_INVALID;
1191c2c66affSColin Finck     }
1192c2c66affSColin Finck     if (!package->num_langids)
1193c2c66affSColin Finck     {
1194c2c66affSColin Finck         return ERROR_SUCCESS;
1195c2c66affSColin Finck     }
1196c2c66affSColin Finck     for (i = 0; i < package->num_langids; i++)
1197c2c66affSColin Finck     {
1198c2c66affSColin Finck         LANGID langid = package->langids[i];
1199c2c66affSColin Finck 
1200c2c66affSColin Finck         if (PRIMARYLANGID( langid ) == LANG_NEUTRAL)
1201c2c66affSColin Finck         {
1202c2c66affSColin Finck             langid = MAKELANGID( PRIMARYLANGID( GetSystemDefaultLangID() ), SUBLANGID( langid ) );
1203c2c66affSColin Finck         }
1204c2c66affSColin Finck         if (SUBLANGID( langid ) == SUBLANG_NEUTRAL)
1205c2c66affSColin Finck         {
1206c2c66affSColin Finck             langid = MAKELANGID( PRIMARYLANGID( langid ), SUBLANGID( GetSystemDefaultLangID() ) );
1207c2c66affSColin Finck         }
1208c2c66affSColin Finck         if (IsValidLocale( langid, LCID_INSTALLED ))
1209c2c66affSColin Finck             return ERROR_SUCCESS;
1210c2c66affSColin Finck     }
1211c2c66affSColin Finck     return ERROR_INSTALL_LANGUAGE_UNSUPPORTED;
1212c2c66affSColin Finck }
1213c2c66affSColin Finck 
get_property(MSIDATABASE * db,const WCHAR * prop)1214b7b9c0c4Swinesync static WCHAR *get_property( MSIDATABASE *db, const WCHAR *prop )
1215c2c66affSColin Finck {
1216b7b9c0c4Swinesync     WCHAR query[MAX_PATH];
1217c2c66affSColin Finck     MSIQUERY *view;
1218c2c66affSColin Finck     MSIRECORD *rec;
1219c2c66affSColin Finck     WCHAR *ret = NULL;
1220c2c66affSColin Finck 
12210272139cSwinesync     swprintf(query, ARRAY_SIZE(query), L"SELECT `Value` FROM `Property` WHERE `Property`='%s'", prop);
1222c2c66affSColin Finck     if (MSI_DatabaseOpenViewW( db, query, &view ) != ERROR_SUCCESS)
1223c2c66affSColin Finck     {
1224c2c66affSColin Finck         return NULL;
1225c2c66affSColin Finck     }
1226c2c66affSColin Finck     if (MSI_ViewExecute( view, 0 ) != ERROR_SUCCESS)
1227c2c66affSColin Finck     {
1228c2c66affSColin Finck         MSI_ViewClose( view );
1229c2c66affSColin Finck         msiobj_release( &view->hdr );
1230c2c66affSColin Finck         return NULL;
1231c2c66affSColin Finck     }
1232c2c66affSColin Finck     if (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS)
1233c2c66affSColin Finck     {
1234*f4be6dc3SMikhail         ret = wcsdup( MSI_RecordGetString( rec, 1 ) );
1235c2c66affSColin Finck         msiobj_release( &rec->hdr );
1236c2c66affSColin Finck     }
1237c2c66affSColin Finck     MSI_ViewClose( view );
1238c2c66affSColin Finck     msiobj_release( &view->hdr );
1239c2c66affSColin Finck     return ret;
1240c2c66affSColin Finck }
1241c2c66affSColin Finck 
get_product_code(MSIDATABASE * db)1242b7b9c0c4Swinesync static WCHAR *get_product_code( MSIDATABASE *db )
1243b7b9c0c4Swinesync {
12440272139cSwinesync     return get_property( db, L"ProductCode" );
1245b7b9c0c4Swinesync }
1246b7b9c0c4Swinesync 
get_product_version(MSIDATABASE * db)1247b7b9c0c4Swinesync static WCHAR *get_product_version( MSIDATABASE *db )
1248b7b9c0c4Swinesync {
12490272139cSwinesync     return get_property( db, L"ProductVersion" );
1250b7b9c0c4Swinesync }
1251b7b9c0c4Swinesync 
get_registered_local_package(const WCHAR * product,WCHAR * localfile)1252b7b9c0c4Swinesync static UINT get_registered_local_package( const WCHAR *product, WCHAR *localfile )
1253c2c66affSColin Finck {
1254c2c66affSColin Finck     MSIINSTALLCONTEXT context;
1255b7b9c0c4Swinesync     WCHAR *filename;
1256b7b9c0c4Swinesync     HKEY props_key;
1257c2c66affSColin Finck     UINT r;
1258c2c66affSColin Finck 
1259c2c66affSColin Finck     r = msi_locate_product( product, &context );
1260c2c66affSColin Finck     if (r != ERROR_SUCCESS)
1261c2c66affSColin Finck         return r;
1262c2c66affSColin Finck 
1263c2c66affSColin Finck     r = MSIREG_OpenInstallProps( product, context, NULL, &props_key, FALSE );
1264c2c66affSColin Finck     if (r != ERROR_SUCCESS)
1265c2c66affSColin Finck         return r;
1266c2c66affSColin Finck 
1267b7b9c0c4Swinesync     filename = msi_reg_get_val_str( props_key, INSTALLPROPERTY_LOCALPACKAGEW );
1268b7b9c0c4Swinesync     RegCloseKey( props_key );
1269c2c66affSColin Finck     if (!filename)
1270b7b9c0c4Swinesync         return ERROR_FUNCTION_FAILED;
1271c2c66affSColin Finck 
1272958f1addSwinesync     lstrcpyW( localfile, filename );
1273*f4be6dc3SMikhail     free( filename );
1274b7b9c0c4Swinesync     return ERROR_SUCCESS;
1275c2c66affSColin Finck }
1276c2c66affSColin Finck 
msi_get_package_code(MSIDATABASE * db)127774196b80Swinesync WCHAR *msi_get_package_code( MSIDATABASE *db )
1278c2c66affSColin Finck {
1279c2c66affSColin Finck     WCHAR *ret;
1280c2c66affSColin Finck     MSISUMMARYINFO *si;
1281c2c66affSColin Finck     UINT r;
1282c2c66affSColin Finck 
1283c2c66affSColin Finck     r = msi_get_suminfo( db->storage, 0, &si );
1284c2c66affSColin Finck     if (r != ERROR_SUCCESS)
1285c2c66affSColin Finck     {
1286c2c66affSColin Finck         r = msi_get_db_suminfo( db, 0, &si );
1287c2c66affSColin Finck         if (r != ERROR_SUCCESS)
1288c2c66affSColin Finck         {
1289c2c66affSColin Finck             WARN("failed to load summary info %u\n", r);
1290c2c66affSColin Finck             return NULL;
1291c2c66affSColin Finck         }
1292c2c66affSColin Finck     }
1293c2c66affSColin Finck     ret = msi_suminfo_dup_string( si, PID_REVNUMBER );
1294c2c66affSColin Finck     msiobj_release( &si->hdr );
1295c2c66affSColin Finck     return ret;
1296c2c66affSColin Finck }
1297c2c66affSColin Finck 
get_local_package(MSIDATABASE * db,WCHAR * localfile)1298b7b9c0c4Swinesync static UINT get_local_package( MSIDATABASE *db, WCHAR *localfile )
1299c2c66affSColin Finck {
1300b7b9c0c4Swinesync     WCHAR *product_code;
1301c2c66affSColin Finck     UINT r;
1302c2c66affSColin Finck 
1303c2c66affSColin Finck     if (!(product_code = get_product_code( db )))
1304c2c66affSColin Finck         return ERROR_INSTALL_PACKAGE_INVALID;
1305b7b9c0c4Swinesync     r = get_registered_local_package( product_code, localfile );
1306*f4be6dc3SMikhail     free( product_code );
1307c2c66affSColin Finck     return r;
1308c2c66affSColin Finck }
1309c2c66affSColin Finck 
msi_set_original_database_property(MSIDATABASE * db,const WCHAR * package)1310c2c66affSColin Finck UINT msi_set_original_database_property( MSIDATABASE *db, const WCHAR *package )
1311c2c66affSColin Finck {
1312c2c66affSColin Finck     UINT r;
1313c2c66affSColin Finck 
1314c2c66affSColin Finck     if (UrlIsW( package, URLIS_URL ))
13150272139cSwinesync         r = msi_set_property( db, L"OriginalDatabase", package, -1 );
1316c2c66affSColin Finck     else if (package[0] == '#')
13170272139cSwinesync         r = msi_set_property( db, L"OriginalDatabase", db->path, -1 );
1318c2c66affSColin Finck     else
1319c2c66affSColin Finck     {
1320c2c66affSColin Finck         DWORD len;
1321c2c66affSColin Finck         WCHAR *path;
1322c2c66affSColin Finck 
1323c2c66affSColin Finck         if (!(len = GetFullPathNameW( package, 0, NULL, NULL ))) return GetLastError();
1324*f4be6dc3SMikhail         if (!(path = malloc( len * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY;
1325c2c66affSColin Finck         len = GetFullPathNameW( package, len, path, NULL );
13260272139cSwinesync         r = msi_set_property( db, L"OriginalDatabase", path, len );
1327*f4be6dc3SMikhail         free( path );
1328c2c66affSColin Finck     }
1329c2c66affSColin Finck     return r;
1330c2c66affSColin Finck }
1331c2c66affSColin Finck 
133205637a5eSMark Jansen #ifdef __REACTOS__
133305637a5eSMark Jansen BOOL WINAPI ApphelpCheckRunAppEx(HANDLE FileHandle, PVOID Unk1, PVOID Unk2, PCWSTR ApplicationName, PVOID Environment, USHORT ExeType, PULONG Reason, PVOID *SdbQueryAppCompatData, PULONG SdbQueryAppCompatDataSize,
133405637a5eSMark Jansen     PVOID *SxsData, PULONG SxsDataSize, PULONG FusionFlags, PULONG64 SomeFlag1, PULONG SomeFlag2);
133505637a5eSMark Jansen BOOL WINAPI SE_DynamicShim(LPCWSTR ProcessImage, PVOID hsdb, PVOID pQueryResult, LPCSTR Module, LPDWORD lpdwDynamicToken);
133605637a5eSMark Jansen PVOID WINAPI SdbInitDatabase(DWORD flags, LPCWSTR path);
133705637a5eSMark Jansen PVOID WINAPI SdbReleaseDatabase(PVOID hsdb);
133805637a5eSMark Jansen 
133905637a5eSMark Jansen #define HID_DOS_PATHS 0x1
134005637a5eSMark Jansen #define SDB_DATABASE_MAIN_SHIM 0x80030000
134105637a5eSMark Jansen 
134205637a5eSMark Jansen #define APPHELP_VALID_RESULT 0x10000
134305637a5eSMark Jansen #define APPHELP_RESULT_FOUND 0x40000
134405637a5eSMark Jansen 
134505637a5eSMark Jansen static void
AppHelpCheckPackage(LPCWSTR szPackage)134605637a5eSMark Jansen AppHelpCheckPackage(LPCWSTR szPackage)
134705637a5eSMark Jansen {
134805637a5eSMark Jansen     USHORT ExeType = 0;
134905637a5eSMark Jansen     ULONG Reason = 0;
135005637a5eSMark Jansen 
135105637a5eSMark Jansen     PVOID QueryResult = NULL;
135205637a5eSMark Jansen     ULONG QueryResultSize = 0;
135305637a5eSMark Jansen 
135405637a5eSMark Jansen     HANDLE Handle = NULL;
135505637a5eSMark Jansen     BOOL Continue = ApphelpCheckRunAppEx(
135605637a5eSMark Jansen         Handle, NULL, NULL, szPackage, NULL, ExeType, &Reason, &QueryResult, &QueryResultSize, NULL,
135705637a5eSMark Jansen         NULL, NULL, NULL, NULL);
135805637a5eSMark Jansen 
135905637a5eSMark Jansen     if (Continue)
136005637a5eSMark Jansen     {
136105637a5eSMark Jansen         if ((Reason & (APPHELP_VALID_RESULT | APPHELP_RESULT_FOUND)) == (APPHELP_VALID_RESULT | APPHELP_RESULT_FOUND))
136205637a5eSMark Jansen         {
136305637a5eSMark Jansen             DWORD dwToken;
136405637a5eSMark Jansen             PVOID hsdb = SdbInitDatabase(HID_DOS_PATHS | SDB_DATABASE_MAIN_SHIM, NULL);
136505637a5eSMark Jansen             if (hsdb)
136605637a5eSMark Jansen             {
136705637a5eSMark Jansen                 BOOL bShim = SE_DynamicShim(szPackage, hsdb, QueryResult, "msi.dll", &dwToken);
1368a0b1a01cSMark Jansen                 ERR("ReactOS HACK(CORE-13283): Used SE_DynamicShim %d!\n", bShim);
136905637a5eSMark Jansen 
137005637a5eSMark Jansen                 SdbReleaseDatabase(hsdb);
137105637a5eSMark Jansen             }
137205637a5eSMark Jansen             else
137305637a5eSMark Jansen             {
137405637a5eSMark Jansen                 ERR("Unable to open SDB_DATABASE_MAIN_SHIM\n");
137505637a5eSMark Jansen             }
137605637a5eSMark Jansen         }
137705637a5eSMark Jansen     }
137805637a5eSMark Jansen 
137905637a5eSMark Jansen     if (QueryResult)
138005637a5eSMark Jansen         RtlFreeHeap(RtlGetProcessHeap(), 0, QueryResult);
138105637a5eSMark Jansen }
138205637a5eSMark Jansen #endif
138305637a5eSMark Jansen 
MSI_OpenPackageW(LPCWSTR szPackage,DWORD dwOptions,MSIPACKAGE ** pPackage)1384a2371385Swinesync UINT MSI_OpenPackageW(LPCWSTR szPackage, DWORD dwOptions, MSIPACKAGE **pPackage)
1385c2c66affSColin Finck {
1386c2c66affSColin Finck     MSIDATABASE *db;
1387c2c66affSColin Finck     MSIPACKAGE *package;
1388c2c66affSColin Finck     MSIHANDLE handle;
138971bffdcdSAmine Khaldi     MSIRECORD *data_row, *info_row;
1390c2c66affSColin Finck     UINT r;
1391c2c66affSColin Finck     WCHAR localfile[MAX_PATH], cachefile[MAX_PATH];
1392c2c66affSColin Finck     LPCWSTR file = szPackage;
1393c2c66affSColin Finck     DWORD index = 0;
1394c2c66affSColin Finck     MSISUMMARYINFO *si;
1395c2c66affSColin Finck     BOOL delete_on_close = FALSE;
1396da848361Swinesync     WCHAR *info_template, *productname, *product_code;
1397da848361Swinesync     MSIINSTALLCONTEXT context;
1398c2c66affSColin Finck 
1399c2c66affSColin Finck     TRACE("%s %p\n", debugstr_w(szPackage), pPackage);
1400c2c66affSColin Finck 
140171bffdcdSAmine Khaldi     MSI_ProcessMessage(NULL, INSTALLMESSAGE_INITIALIZE, 0);
140271bffdcdSAmine Khaldi 
1403c2c66affSColin Finck     localfile[0] = 0;
1404c2c66affSColin Finck     if( szPackage[0] == '#' )
1405c2c66affSColin Finck     {
1406958f1addSwinesync         handle = wcstol(&szPackage[1], NULL, 10);
1407b720e4c0Swinesync         if (!(db = msihandle2msiinfo(handle, MSIHANDLETYPE_DATABASE)))
1408c2c66affSColin Finck             return ERROR_INVALID_HANDLE;
1409c2c66affSColin Finck     }
1410c2c66affSColin Finck     else
1411c2c66affSColin Finck     {
1412b7b9c0c4Swinesync         WCHAR *product_version = NULL;
1413b7b9c0c4Swinesync 
1414c2c66affSColin Finck         if ( UrlIsW( szPackage, URLIS_URL ) )
1415c2c66affSColin Finck         {
1416c2c66affSColin Finck             r = msi_download_file( szPackage, cachefile );
1417c2c66affSColin Finck             if (r != ERROR_SUCCESS)
1418c2c66affSColin Finck                 return r;
1419c2c66affSColin Finck 
1420c2c66affSColin Finck             file = cachefile;
1421c2c66affSColin Finck         }
142205637a5eSMark Jansen #ifdef __REACTOS__
142305637a5eSMark Jansen         AppHelpCheckPackage(file);
142405637a5eSMark Jansen #endif
142505637a5eSMark Jansen 
1426b7b9c0c4Swinesync         r = MSI_OpenDatabaseW( file, MSIDBOPEN_READONLY, &db );
1427b7b9c0c4Swinesync         if (r != ERROR_SUCCESS)
1428b7b9c0c4Swinesync         {
1429b7b9c0c4Swinesync             if (GetFileAttributesW( file ) == INVALID_FILE_ATTRIBUTES)
1430b7b9c0c4Swinesync                 return ERROR_FILE_NOT_FOUND;
1431b7b9c0c4Swinesync             return r;
1432b7b9c0c4Swinesync         }
1433b7b9c0c4Swinesync         r = get_local_package( db, localfile );
1434c2c66affSColin Finck         if (r != ERROR_SUCCESS || GetFileAttributesW( localfile ) == INVALID_FILE_ATTRIBUTES)
1435c2c66affSColin Finck         {
143663bb43adSJérôme Gardou             DWORD localfile_attr;
143763bb43adSJérôme Gardou 
14380272139cSwinesync             r = msi_create_empty_local_file( localfile, L".msi" );
1439c2c66affSColin Finck             if (r != ERROR_SUCCESS)
1440b7b9c0c4Swinesync             {
1441b7b9c0c4Swinesync                 msiobj_release( &db->hdr );
1442c2c66affSColin Finck                 return r;
1443b7b9c0c4Swinesync             }
1444c2c66affSColin Finck 
1445c2c66affSColin Finck             if (!CopyFileW( file, localfile, FALSE ))
1446c2c66affSColin Finck             {
1447c2c66affSColin Finck                 r = GetLastError();
1448c2c66affSColin Finck                 WARN("unable to copy package %s to %s (%u)\n", debugstr_w(file), debugstr_w(localfile), r);
1449c2c66affSColin Finck                 DeleteFileW( localfile );
1450b7b9c0c4Swinesync                 msiobj_release( &db->hdr );
1451c2c66affSColin Finck                 return r;
1452c2c66affSColin Finck             }
1453c2c66affSColin Finck             delete_on_close = TRUE;
145463bb43adSJérôme Gardou 
145563bb43adSJérôme Gardou             /* Remove read-only bit, we are opening it with write access in MSI_OpenDatabaseW below. */
145663bb43adSJérôme Gardou             localfile_attr = GetFileAttributesW( localfile );
145763bb43adSJérôme Gardou             if (localfile_attr & FILE_ATTRIBUTE_READONLY)
145863bb43adSJérôme Gardou                 SetFileAttributesW( localfile, localfile_attr & ~FILE_ATTRIBUTE_READONLY);
1459c2c66affSColin Finck         }
1460a2371385Swinesync         else if (dwOptions & WINE_OPENPACKAGEFLAGS_RECACHE)
1461a2371385Swinesync         {
1462a2371385Swinesync             if (!CopyFileW( file, localfile, FALSE ))
1463a2371385Swinesync             {
1464a2371385Swinesync                 r = GetLastError();
1465a2371385Swinesync                 WARN("unable to update cached package (%u)\n", r);
1466a2371385Swinesync                 msiobj_release( &db->hdr );
1467a2371385Swinesync                 return r;
1468a2371385Swinesync             }
1469a2371385Swinesync         }
1470b7b9c0c4Swinesync         else
1471b7b9c0c4Swinesync             product_version = get_product_version( db );
1472b7b9c0c4Swinesync         msiobj_release( &db->hdr );
1473c2c66affSColin Finck         TRACE("opening package %s\n", debugstr_w( localfile ));
1474c2c66affSColin Finck         r = MSI_OpenDatabaseW( localfile, MSIDBOPEN_TRANSACT, &db );
1475c2c66affSColin Finck         if (r != ERROR_SUCCESS)
1476*f4be6dc3SMikhail         {
1477*f4be6dc3SMikhail             free( product_version );
1478c2c66affSColin Finck             return r;
1479*f4be6dc3SMikhail         }
1480b7b9c0c4Swinesync 
1481b7b9c0c4Swinesync         if (product_version)
1482b7b9c0c4Swinesync         {
1483b7b9c0c4Swinesync             WCHAR *cache_version = get_product_version( db );
1484b7b9c0c4Swinesync             if (!product_version != !cache_version ||
1485958f1addSwinesync                     (product_version && wcscmp(product_version, cache_version)))
1486b7b9c0c4Swinesync             {
1487b7b9c0c4Swinesync                 msiobj_release( &db->hdr );
1488*f4be6dc3SMikhail                 free( product_version );
1489*f4be6dc3SMikhail                 free( cache_version );
1490b7b9c0c4Swinesync                 return ERROR_PRODUCT_VERSION;
1491b7b9c0c4Swinesync             }
1492*f4be6dc3SMikhail             free( product_version );
1493*f4be6dc3SMikhail             free( cache_version );
1494b7b9c0c4Swinesync         }
1495c2c66affSColin Finck     }
149634c2011cSwinesync     package = MSI_CreatePackage( db );
1497c2c66affSColin Finck     msiobj_release( &db->hdr );
1498c2c66affSColin Finck     if (!package) return ERROR_INSTALL_PACKAGE_INVALID;
1499*f4be6dc3SMikhail     package->localfile = wcsdup( localfile );
1500c2c66affSColin Finck     package->delete_on_close = delete_on_close;
1501c2c66affSColin Finck 
1502c2c66affSColin Finck     r = msi_get_suminfo( db->storage, 0, &si );
1503c2c66affSColin Finck     if (r != ERROR_SUCCESS)
1504c2c66affSColin Finck     {
1505c2c66affSColin Finck         r = msi_get_db_suminfo( db, 0, &si );
1506c2c66affSColin Finck         if (r != ERROR_SUCCESS)
1507c2c66affSColin Finck         {
1508c2c66affSColin Finck             WARN("failed to load summary info\n");
1509c2c66affSColin Finck             msiobj_release( &package->hdr );
1510c2c66affSColin Finck             return ERROR_INSTALL_PACKAGE_INVALID;
1511c2c66affSColin Finck         }
1512c2c66affSColin Finck     }
1513c2c66affSColin Finck     r = parse_suminfo( si, package );
1514c2c66affSColin Finck     msiobj_release( &si->hdr );
1515c2c66affSColin Finck     if (r != ERROR_SUCCESS)
1516c2c66affSColin Finck     {
1517c2c66affSColin Finck         WARN("failed to parse summary info %u\n", r);
1518c2c66affSColin Finck         msiobj_release( &package->hdr );
1519c2c66affSColin Finck         return r;
1520c2c66affSColin Finck     }
1521c2c66affSColin Finck     r = validate_package( package );
1522c2c66affSColin Finck     if (r != ERROR_SUCCESS)
1523c2c66affSColin Finck     {
1524c2c66affSColin Finck         msiobj_release( &package->hdr );
1525c2c66affSColin Finck         return r;
1526c2c66affSColin Finck     }
15270272139cSwinesync     msi_set_property( package->db, L"DATABASE", db->path, -1 );
1528c2c66affSColin Finck     set_installed_prop( package );
1529c2c66affSColin Finck     msi_set_context( package );
1530c2c66affSColin Finck 
1531da848361Swinesync     product_code = get_product_code( db );
1532da848361Swinesync     if (msi_locate_product( product_code, &context ) == ERROR_SUCCESS)
1533da848361Swinesync     {
1534da848361Swinesync         TRACE("product already registered\n");
15350272139cSwinesync         msi_set_property( package->db, L"ProductToBeRegistered", L"1", -1 );
1536da848361Swinesync     }
1537*f4be6dc3SMikhail     free( product_code );
1538da848361Swinesync 
1539c2c66affSColin Finck     while (1)
1540c2c66affSColin Finck     {
1541c2c66affSColin Finck         WCHAR patch_code[GUID_SIZE];
1542c2c66affSColin Finck         r = MsiEnumPatchesExW( package->ProductCode, NULL, package->Context,
1543c2c66affSColin Finck                                MSIPATCHSTATE_APPLIED, index, patch_code, NULL, NULL, NULL, NULL );
1544c2c66affSColin Finck         if (r != ERROR_SUCCESS)
1545c2c66affSColin Finck             break;
1546c2c66affSColin Finck 
1547c2c66affSColin Finck         TRACE("found registered patch %s\n", debugstr_w(patch_code));
1548c2c66affSColin Finck 
1549c2c66affSColin Finck         r = msi_apply_registered_patch( package, patch_code );
1550c2c66affSColin Finck         if (r != ERROR_SUCCESS)
1551c2c66affSColin Finck         {
1552c2c66affSColin Finck             ERR("registered patch failed to apply %u\n", r);
1553c2c66affSColin Finck             msiobj_release( &package->hdr );
1554c2c66affSColin Finck             return r;
1555c2c66affSColin Finck         }
1556c2c66affSColin Finck         index++;
1557c2c66affSColin Finck     }
1558c2c66affSColin Finck     if (index) msi_adjust_privilege_properties( package );
1559c2c66affSColin Finck 
1560c2c66affSColin Finck     r = msi_set_original_database_property( package->db, szPackage );
1561c2c66affSColin Finck     if (r != ERROR_SUCCESS)
1562c2c66affSColin Finck     {
1563c2c66affSColin Finck         msiobj_release( &package->hdr );
1564c2c66affSColin Finck         return r;
1565c2c66affSColin Finck     }
1566c2c66affSColin Finck     if (gszLogFile)
1567c2c66affSColin Finck         package->log_file = CreateFileW( gszLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
1568c2c66affSColin Finck                                          OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
156971bffdcdSAmine Khaldi 
157071bffdcdSAmine Khaldi     /* FIXME: when should these messages be sent? */
157171bffdcdSAmine Khaldi     data_row = MSI_CreateRecord(3);
157271bffdcdSAmine Khaldi     if (!data_row)
157371bffdcdSAmine Khaldi 	return ERROR_OUTOFMEMORY;
157471bffdcdSAmine Khaldi     MSI_RecordSetStringW(data_row, 0, NULL);
157571bffdcdSAmine Khaldi     MSI_RecordSetInteger(data_row, 1, 0);
157671bffdcdSAmine Khaldi     MSI_RecordSetInteger(data_row, 2, package->num_langids ? package->langids[0] : 0);
157771bffdcdSAmine Khaldi     MSI_RecordSetInteger(data_row, 3, msi_get_string_table_codepage(package->db->strings));
157871bffdcdSAmine Khaldi     MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_COMMONDATA, data_row);
157971bffdcdSAmine Khaldi 
158071bffdcdSAmine Khaldi     info_row = MSI_CreateRecord(0);
158171bffdcdSAmine Khaldi     if (!info_row)
158271bffdcdSAmine Khaldi     {
158371bffdcdSAmine Khaldi 	msiobj_release(&data_row->hdr);
158471bffdcdSAmine Khaldi 	return ERROR_OUTOFMEMORY;
158571bffdcdSAmine Khaldi     }
158671bffdcdSAmine Khaldi     info_template = msi_get_error_message(package->db, MSIERR_INFO_LOGGINGSTART);
158771bffdcdSAmine Khaldi     MSI_RecordSetStringW(info_row, 0, info_template);
1588*f4be6dc3SMikhail     free(info_template);
158971bffdcdSAmine Khaldi     MSI_ProcessMessage(package, INSTALLMESSAGE_INFO|MB_ICONHAND, info_row);
159071bffdcdSAmine Khaldi 
159171bffdcdSAmine Khaldi     MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, data_row);
159271bffdcdSAmine Khaldi 
159371bffdcdSAmine Khaldi     productname = msi_dup_property(package->db, INSTALLPROPERTY_PRODUCTNAMEW);
159471bffdcdSAmine Khaldi     MSI_RecordSetInteger(data_row, 1, 1);
159571bffdcdSAmine Khaldi     MSI_RecordSetStringW(data_row, 2, productname);
159671bffdcdSAmine Khaldi     MSI_RecordSetStringW(data_row, 3, NULL);
159771bffdcdSAmine Khaldi     MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, data_row);
159871bffdcdSAmine Khaldi 
1599*f4be6dc3SMikhail     free(productname);
160071bffdcdSAmine Khaldi     msiobj_release(&info_row->hdr);
160171bffdcdSAmine Khaldi     msiobj_release(&data_row->hdr);
160271bffdcdSAmine Khaldi 
1603c2c66affSColin Finck     *pPackage = package;
1604c2c66affSColin Finck     return ERROR_SUCCESS;
1605c2c66affSColin Finck }
1606c2c66affSColin Finck 
MsiOpenPackageExW(const WCHAR * szPackage,DWORD dwOptions,MSIHANDLE * phPackage)160702f995b2Swinesync UINT WINAPI MsiOpenPackageExW( const WCHAR *szPackage, DWORD dwOptions, MSIHANDLE *phPackage )
1608c2c66affSColin Finck {
1609c2c66affSColin Finck     MSIPACKAGE *package = NULL;
1610c2c66affSColin Finck     UINT ret;
1611c2c66affSColin Finck 
161202f995b2Swinesync     TRACE( "%s, %#lx, %p\n", debugstr_w(szPackage), dwOptions, phPackage );
1613c2c66affSColin Finck 
1614c2c66affSColin Finck     if( !szPackage || !phPackage )
1615c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
1616c2c66affSColin Finck 
1617c2c66affSColin Finck     if ( !*szPackage )
1618c2c66affSColin Finck     {
1619c2c66affSColin Finck         FIXME("Should create an empty database and package\n");
1620c2c66affSColin Finck         return ERROR_FUNCTION_FAILED;
1621c2c66affSColin Finck     }
1622c2c66affSColin Finck 
1623c2c66affSColin Finck     if( dwOptions )
162402f995b2Swinesync         FIXME( "dwOptions %#lx not supported\n", dwOptions );
1625c2c66affSColin Finck 
1626a2371385Swinesync     ret = MSI_OpenPackageW( szPackage, 0, &package );
1627c2c66affSColin Finck     if( ret == ERROR_SUCCESS )
1628c2c66affSColin Finck     {
1629c2c66affSColin Finck         *phPackage = alloc_msihandle( &package->hdr );
1630c2c66affSColin Finck         if (! *phPackage)
1631c2c66affSColin Finck             ret = ERROR_NOT_ENOUGH_MEMORY;
1632c2c66affSColin Finck         msiobj_release( &package->hdr );
1633c2c66affSColin Finck     }
163471bffdcdSAmine Khaldi     else
163571bffdcdSAmine Khaldi         MSI_ProcessMessage(NULL, INSTALLMESSAGE_TERMINATE, 0);
1636c2c66affSColin Finck 
1637c2c66affSColin Finck     return ret;
1638c2c66affSColin Finck }
1639c2c66affSColin Finck 
MsiOpenPackageW(LPCWSTR szPackage,MSIHANDLE * phPackage)1640c2c66affSColin Finck UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
1641c2c66affSColin Finck {
1642c2c66affSColin Finck     return MsiOpenPackageExW( szPackage, 0, phPackage );
1643c2c66affSColin Finck }
1644c2c66affSColin Finck 
MsiOpenPackageExA(LPCSTR szPackage,DWORD dwOptions,MSIHANDLE * phPackage)1645c2c66affSColin Finck UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
1646c2c66affSColin Finck {
1647c2c66affSColin Finck     LPWSTR szwPack = NULL;
1648c2c66affSColin Finck     UINT ret;
1649c2c66affSColin Finck 
1650c2c66affSColin Finck     if( szPackage )
1651c2c66affSColin Finck     {
1652c2c66affSColin Finck         szwPack = strdupAtoW( szPackage );
1653c2c66affSColin Finck         if( !szwPack )
1654c2c66affSColin Finck             return ERROR_OUTOFMEMORY;
1655c2c66affSColin Finck     }
1656c2c66affSColin Finck 
1657c2c66affSColin Finck     ret = MsiOpenPackageExW( szwPack, dwOptions, phPackage );
1658c2c66affSColin Finck 
1659*f4be6dc3SMikhail     free( szwPack );
1660c2c66affSColin Finck 
1661c2c66affSColin Finck     return ret;
1662c2c66affSColin Finck }
1663c2c66affSColin Finck 
MsiOpenPackageA(LPCSTR szPackage,MSIHANDLE * phPackage)1664c2c66affSColin Finck UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
1665c2c66affSColin Finck {
1666c2c66affSColin Finck     return MsiOpenPackageExA( szPackage, 0, phPackage );
1667c2c66affSColin Finck }
1668c2c66affSColin Finck 
MsiGetActiveDatabase(MSIHANDLE hInstall)1669c2c66affSColin Finck MSIHANDLE WINAPI MsiGetActiveDatabase( MSIHANDLE hInstall )
1670c2c66affSColin Finck {
1671c2c66affSColin Finck     MSIPACKAGE *package;
1672c2c66affSColin Finck     MSIHANDLE handle = 0;
1673b74b77aaSwinesync     MSIHANDLE remote;
1674c2c66affSColin Finck 
167502f995b2Swinesync     TRACE( "%lu\n", hInstall );
1676c2c66affSColin Finck 
1677c2c66affSColin Finck     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
1678c2c66affSColin Finck     if( package)
1679c2c66affSColin Finck     {
1680c2c66affSColin Finck         handle = alloc_msihandle( &package->db->hdr );
1681c2c66affSColin Finck         msiobj_release( &package->hdr );
1682c2c66affSColin Finck     }
1683b74b77aaSwinesync     else if ((remote = msi_get_remote(hInstall)))
1684c2c66affSColin Finck     {
16852a9ae858Swinesync         __TRY
16862a9ae858Swinesync         {
1687bf1ca658Swinesync             handle = remote_GetActiveDatabase(remote);
16887cc54a4fSwinesync             handle = alloc_msi_remote_handle(handle);
1689c2c66affSColin Finck         }
16902a9ae858Swinesync         __EXCEPT(rpc_filter)
16912a9ae858Swinesync         {
16922a9ae858Swinesync             handle = 0;
16932a9ae858Swinesync         }
16942a9ae858Swinesync         __ENDTRY
16952a9ae858Swinesync     }
1696c2c66affSColin Finck 
1697c2c66affSColin Finck     return handle;
1698c2c66affSColin Finck }
1699c2c66affSColin Finck 
internal_ui_handler(MSIPACKAGE * package,INSTALLMESSAGE eMessageType,MSIRECORD * record,LPCWSTR message)170071bffdcdSAmine Khaldi static INT internal_ui_handler(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record, LPCWSTR message)
1701c2c66affSColin Finck {
170271bffdcdSAmine Khaldi     if (!package || (package->ui_level & INSTALLUILEVEL_MASK) == INSTALLUILEVEL_NONE)
170371bffdcdSAmine Khaldi         return 0;
170471bffdcdSAmine Khaldi 
170571bffdcdSAmine Khaldi     /* todo: check if message needs additional styles (topmost/foreground/modality?) */
170671bffdcdSAmine Khaldi 
170771bffdcdSAmine Khaldi     switch (eMessageType & 0xff000000)
170871bffdcdSAmine Khaldi     {
170971bffdcdSAmine Khaldi     case INSTALLMESSAGE_FATALEXIT:
171071bffdcdSAmine Khaldi     case INSTALLMESSAGE_ERROR:
171171bffdcdSAmine Khaldi     case INSTALLMESSAGE_OUTOFDISKSPACE:
171271bffdcdSAmine Khaldi         if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0;
171371bffdcdSAmine Khaldi         if (!(eMessageType & MB_ICONMASK))
171471bffdcdSAmine Khaldi             eMessageType |= MB_ICONEXCLAMATION;
17150272139cSwinesync         return MessageBoxW(gUIhwnd, message, L"Windows Installer", eMessageType & 0x00ffffff);
171671bffdcdSAmine Khaldi     case INSTALLMESSAGE_WARNING:
171771bffdcdSAmine Khaldi         if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0;
171871bffdcdSAmine Khaldi         if (!(eMessageType & MB_ICONMASK))
171971bffdcdSAmine Khaldi             eMessageType |= MB_ICONASTERISK;
17200272139cSwinesync         return MessageBoxW(gUIhwnd, message, L"Windows Installer", eMessageType & 0x00ffffff);
172171bffdcdSAmine Khaldi     case INSTALLMESSAGE_USER:
172271bffdcdSAmine Khaldi         if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0;
172371bffdcdSAmine Khaldi         if (!(eMessageType & MB_ICONMASK))
172471bffdcdSAmine Khaldi             eMessageType |= MB_USERICON;
17250272139cSwinesync         return MessageBoxW(gUIhwnd, message, L"Windows Installer", eMessageType & 0x00ffffff);
172671bffdcdSAmine Khaldi     case INSTALLMESSAGE_INFO:
172771bffdcdSAmine Khaldi     case INSTALLMESSAGE_INITIALIZE:
172871bffdcdSAmine Khaldi     case INSTALLMESSAGE_TERMINATE:
1729f8b992f2SAmine Khaldi     case INSTALLMESSAGE_INSTALLSTART:
1730f8b992f2SAmine Khaldi     case INSTALLMESSAGE_INSTALLEND:
173171bffdcdSAmine Khaldi         return 0;
173271bffdcdSAmine Khaldi     case INSTALLMESSAGE_SHOWDIALOG:
173371bffdcdSAmine Khaldi     {
173471bffdcdSAmine Khaldi         LPWSTR dialog = msi_dup_record_field(record, 0);
173571bffdcdSAmine Khaldi         INT rc = ACTION_DialogBox(package, dialog);
1736*f4be6dc3SMikhail         free(dialog);
173771bffdcdSAmine Khaldi         return rc;
173871bffdcdSAmine Khaldi     }
173971bffdcdSAmine Khaldi     case INSTALLMESSAGE_ACTIONSTART:
174071bffdcdSAmine Khaldi     {
174171bffdcdSAmine Khaldi         LPWSTR deformatted;
174271bffdcdSAmine Khaldi         MSIRECORD *uirow = MSI_CreateRecord(1);
174371bffdcdSAmine Khaldi         if (!uirow) return -1;
174471bffdcdSAmine Khaldi         deformat_string(package, MSI_RecordGetString(record, 2), &deformatted);
174571bffdcdSAmine Khaldi         MSI_RecordSetStringW(uirow, 1, deformatted);
17460272139cSwinesync         msi_event_fire(package, L"ActionText", uirow);
174771bffdcdSAmine Khaldi 
1748*f4be6dc3SMikhail         free(deformatted);
174971bffdcdSAmine Khaldi         msiobj_release(&uirow->hdr);
175071bffdcdSAmine Khaldi         return 1;
175171bffdcdSAmine Khaldi     }
175271bffdcdSAmine Khaldi     case INSTALLMESSAGE_ACTIONDATA:
175371bffdcdSAmine Khaldi     {
175471bffdcdSAmine Khaldi         MSIRECORD *uirow = MSI_CreateRecord(1);
175571bffdcdSAmine Khaldi         if (!uirow) return -1;
175671bffdcdSAmine Khaldi         MSI_RecordSetStringW(uirow, 1, message);
17570272139cSwinesync         msi_event_fire(package, L"ActionData", uirow);
175871bffdcdSAmine Khaldi         msiobj_release(&uirow->hdr);
175971bffdcdSAmine Khaldi 
176071bffdcdSAmine Khaldi         if (package->action_progress_increment)
176171bffdcdSAmine Khaldi         {
176271bffdcdSAmine Khaldi             uirow = MSI_CreateRecord(2);
176371bffdcdSAmine Khaldi             if (!uirow) return -1;
176471bffdcdSAmine Khaldi             MSI_RecordSetInteger(uirow, 1, 2);
176571bffdcdSAmine Khaldi             MSI_RecordSetInteger(uirow, 2, package->action_progress_increment);
17660272139cSwinesync             msi_event_fire(package, L"SetProgress", uirow);
176771bffdcdSAmine Khaldi             msiobj_release(&uirow->hdr);
176871bffdcdSAmine Khaldi         }
176971bffdcdSAmine Khaldi         return 1;
177071bffdcdSAmine Khaldi     }
177171bffdcdSAmine Khaldi     case INSTALLMESSAGE_PROGRESS:
17720272139cSwinesync         msi_event_fire(package, L"SetProgress", record);
177371bffdcdSAmine Khaldi         return 1;
177471bffdcdSAmine Khaldi     case INSTALLMESSAGE_COMMONDATA:
177571bffdcdSAmine Khaldi         switch (MSI_RecordGetInteger(record, 1))
177671bffdcdSAmine Khaldi         {
177771bffdcdSAmine Khaldi         case 0:
177871bffdcdSAmine Khaldi         case 1:
177971bffdcdSAmine Khaldi             /* do nothing */
178071bffdcdSAmine Khaldi             return 0;
178171bffdcdSAmine Khaldi         default:
178271bffdcdSAmine Khaldi             /* fall through */
178371bffdcdSAmine Khaldi             ;
178471bffdcdSAmine Khaldi         }
178571bffdcdSAmine Khaldi     default:
178671bffdcdSAmine Khaldi         FIXME("internal UI not implemented for message 0x%08x (UI level = %x)\n", eMessageType, package->ui_level);
178771bffdcdSAmine Khaldi         return 0;
178871bffdcdSAmine Khaldi     }
178971bffdcdSAmine Khaldi }
179071bffdcdSAmine Khaldi 
179171bffdcdSAmine Khaldi static const struct
179271bffdcdSAmine Khaldi {
179371bffdcdSAmine Khaldi     int id;
179471bffdcdSAmine Khaldi     const WCHAR *text;
179571bffdcdSAmine Khaldi }
179671bffdcdSAmine Khaldi internal_errors[] =
179771bffdcdSAmine Khaldi {
17980272139cSwinesync     {2726, L"DEBUG: Error [1]:  Action not found: [2]"},
179971bffdcdSAmine Khaldi     {0}
180071bffdcdSAmine Khaldi };
180171bffdcdSAmine Khaldi 
get_internal_error_message(int error)180271bffdcdSAmine Khaldi static LPCWSTR get_internal_error_message(int error)
180371bffdcdSAmine Khaldi {
180471bffdcdSAmine Khaldi     int i = 0;
180571bffdcdSAmine Khaldi 
180671bffdcdSAmine Khaldi     while (internal_errors[i].id != 0)
180771bffdcdSAmine Khaldi     {
180871bffdcdSAmine Khaldi         if (internal_errors[i].id == error)
180971bffdcdSAmine Khaldi             return internal_errors[i].text;
181071bffdcdSAmine Khaldi         i++;
181171bffdcdSAmine Khaldi     }
181271bffdcdSAmine Khaldi 
181371bffdcdSAmine Khaldi     FIXME("missing error message %d\n", error);
181471bffdcdSAmine Khaldi     return NULL;
181571bffdcdSAmine Khaldi }
181671bffdcdSAmine Khaldi 
181771bffdcdSAmine Khaldi /* Returned string must be freed */
msi_get_error_message(MSIDATABASE * db,int error)181871bffdcdSAmine Khaldi LPWSTR msi_get_error_message(MSIDATABASE *db, int error)
181971bffdcdSAmine Khaldi {
182071bffdcdSAmine Khaldi     MSIRECORD *record;
182171bffdcdSAmine Khaldi     LPWSTR ret = NULL;
182271bffdcdSAmine Khaldi 
18230272139cSwinesync     if ((record = MSI_QueryGetRecord(db, L"SELECT `Message` FROM `Error` WHERE `Error` = %d", error)))
182471bffdcdSAmine Khaldi     {
182571bffdcdSAmine Khaldi         ret = msi_dup_record_field(record, 1);
182671bffdcdSAmine Khaldi         msiobj_release(&record->hdr);
182771bffdcdSAmine Khaldi     }
182871bffdcdSAmine Khaldi     else if (error < 2000)
182971bffdcdSAmine Khaldi     {
183071bffdcdSAmine Khaldi         int len = LoadStringW(msi_hInstance, IDS_ERROR_BASE + error, (LPWSTR) &ret, 0);
183171bffdcdSAmine Khaldi         if (len)
183271bffdcdSAmine Khaldi         {
1833*f4be6dc3SMikhail             ret = malloc((len + 1) * sizeof(WCHAR));
183471bffdcdSAmine Khaldi             LoadStringW(msi_hInstance, IDS_ERROR_BASE + error, ret, len + 1);
183571bffdcdSAmine Khaldi         }
183671bffdcdSAmine Khaldi         else
183771bffdcdSAmine Khaldi             ret = NULL;
183871bffdcdSAmine Khaldi     }
183971bffdcdSAmine Khaldi 
184071bffdcdSAmine Khaldi     return ret;
184171bffdcdSAmine Khaldi }
184271bffdcdSAmine Khaldi 
MSI_ProcessMessageVerbatim(MSIPACKAGE * package,INSTALLMESSAGE eMessageType,MSIRECORD * record)184371bffdcdSAmine Khaldi INT MSI_ProcessMessageVerbatim(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record)
184471bffdcdSAmine Khaldi {
184571bffdcdSAmine Khaldi     LPWSTR message = {0};
1846f8b992f2SAmine Khaldi     DWORD len;
1847f8b992f2SAmine Khaldi     DWORD log_type = 1 << (eMessageType >> 24);
184871bffdcdSAmine Khaldi     UINT res;
1849c2c66affSColin Finck     INT rc = 0;
1850c2c66affSColin Finck     char *msg;
1851c2c66affSColin Finck 
1852c2c66affSColin Finck     TRACE("%x\n", eMessageType);
185371bffdcdSAmine Khaldi     if (TRACE_ON(msi)) dump_record(record);
1854c2c66affSColin Finck 
185571bffdcdSAmine Khaldi     if (!package || !record)
185671bffdcdSAmine Khaldi         message = NULL;
185771bffdcdSAmine Khaldi     else {
185871bffdcdSAmine Khaldi         res = MSI_FormatRecordW(package, record, message, &len);
185971bffdcdSAmine Khaldi         if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
186071bffdcdSAmine Khaldi             return res;
186171bffdcdSAmine Khaldi         len++;
1862*f4be6dc3SMikhail         message = malloc(len * sizeof(WCHAR));
186371bffdcdSAmine Khaldi         if (!message) return ERROR_OUTOFMEMORY;
186471bffdcdSAmine Khaldi         MSI_FormatRecordW(package, record, message, &len);
1865c2c66affSColin Finck     }
1866c2c66affSColin Finck 
1867026a2db6Swinesync     /* convert it to ANSI */
1868c2c66affSColin Finck     len = WideCharToMultiByte( CP_ACP, 0, message, -1, NULL, 0, NULL, NULL );
1869*f4be6dc3SMikhail     msg = malloc( len );
1870c2c66affSColin Finck     WideCharToMultiByte( CP_ACP, 0, message, -1, msg, len, NULL, NULL );
1871c2c66affSColin Finck 
187271bffdcdSAmine Khaldi     if (gUIHandlerRecord && (gUIFilterRecord & log_type))
1873c2c66affSColin Finck     {
187471bffdcdSAmine Khaldi         MSIHANDLE rec = alloc_msihandle(&record->hdr);
187502f995b2Swinesync         TRACE( "calling UI handler %p(pvContext = %p, iMessageType = %#x, hRecord = %lu)\n",
187671bffdcdSAmine Khaldi                gUIHandlerRecord, gUIContextRecord, eMessageType, rec );
187771bffdcdSAmine Khaldi         rc = gUIHandlerRecord( gUIContextRecord, eMessageType, rec );
1878c2c66affSColin Finck         MsiCloseHandle( rec );
1879c2c66affSColin Finck     }
188071bffdcdSAmine Khaldi     if (!rc && gUIHandlerW && (gUIFilter & log_type))
188171bffdcdSAmine Khaldi     {
188202f995b2Swinesync         TRACE( "calling UI handler %p(pvContext = %p, iMessageType = %#x, szMessage = %s)\n",
188371bffdcdSAmine Khaldi                gUIHandlerW, gUIContext, eMessageType, debugstr_w(message) );
188471bffdcdSAmine Khaldi         rc = gUIHandlerW( gUIContext, eMessageType, message );
188571bffdcdSAmine Khaldi     }
188671bffdcdSAmine Khaldi     else if (!rc && gUIHandlerA && (gUIFilter & log_type))
188771bffdcdSAmine Khaldi     {
188802f995b2Swinesync         TRACE( "calling UI handler %p(pvContext = %p, iMessageType = %#x, szMessage = %s)\n",
188971bffdcdSAmine Khaldi                gUIHandlerA, gUIContext, eMessageType, debugstr_a(msg) );
189071bffdcdSAmine Khaldi         rc = gUIHandlerA( gUIContext, eMessageType, msg );
189171bffdcdSAmine Khaldi     }
1892c2c66affSColin Finck 
189371bffdcdSAmine Khaldi     if (!rc)
189471bffdcdSAmine Khaldi         rc = internal_ui_handler(package, eMessageType, record, message);
189571bffdcdSAmine Khaldi 
189671bffdcdSAmine Khaldi     if (!rc && package && package->log_file != INVALID_HANDLE_VALUE &&
1897c2c66affSColin Finck         (eMessageType & 0xff000000) != INSTALLMESSAGE_PROGRESS)
1898c2c66affSColin Finck     {
1899c2c66affSColin Finck         DWORD written;
1900c2c66affSColin Finck         WriteFile( package->log_file, msg, len - 1, &written, NULL );
1901c2c66affSColin Finck         WriteFile( package->log_file, "\n", 1, &written, NULL );
1902c2c66affSColin Finck     }
1903*f4be6dc3SMikhail     free( msg );
1904*f4be6dc3SMikhail     free( message );
1905c2c66affSColin Finck 
190671bffdcdSAmine Khaldi     return rc;
190771bffdcdSAmine Khaldi }
190871bffdcdSAmine Khaldi 
MSI_ProcessMessage(MSIPACKAGE * package,INSTALLMESSAGE eMessageType,MSIRECORD * record)190971bffdcdSAmine Khaldi INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record )
191071bffdcdSAmine Khaldi {
1911c2c66affSColin Finck     switch (eMessageType & 0xff000000)
1912c2c66affSColin Finck     {
191371bffdcdSAmine Khaldi     case INSTALLMESSAGE_FATALEXIT:
191471bffdcdSAmine Khaldi     case INSTALLMESSAGE_ERROR:
191571bffdcdSAmine Khaldi     case INSTALLMESSAGE_WARNING:
191671bffdcdSAmine Khaldi     case INSTALLMESSAGE_USER:
191771bffdcdSAmine Khaldi     case INSTALLMESSAGE_INFO:
191871bffdcdSAmine Khaldi     case INSTALLMESSAGE_OUTOFDISKSPACE:
191971bffdcdSAmine Khaldi         if (MSI_RecordGetInteger(record, 1) != MSI_NULL_INTEGER)
1920c2c66affSColin Finck         {
192171bffdcdSAmine Khaldi             /* error message */
192271bffdcdSAmine Khaldi 
192371bffdcdSAmine Khaldi             LPWSTR template;
192471bffdcdSAmine Khaldi             LPWSTR template_rec = NULL, template_prefix = NULL;
192571bffdcdSAmine Khaldi             int error = MSI_RecordGetInteger(record, 1);
192671bffdcdSAmine Khaldi 
192771bffdcdSAmine Khaldi             if (MSI_RecordIsNull(record, 0))
192871bffdcdSAmine Khaldi             {
192971bffdcdSAmine Khaldi                 if (error >= 32)
193071bffdcdSAmine Khaldi                 {
193171bffdcdSAmine Khaldi                     template_rec = msi_get_error_message(package->db, error);
193271bffdcdSAmine Khaldi 
193371bffdcdSAmine Khaldi                     if (!template_rec && error >= 2000)
193471bffdcdSAmine Khaldi                     {
193571bffdcdSAmine Khaldi                         /* internal error, not localized */
193671bffdcdSAmine Khaldi                         if ((template_rec = (LPWSTR) get_internal_error_message(error)))
193771bffdcdSAmine Khaldi                         {
193871bffdcdSAmine Khaldi                             MSI_RecordSetStringW(record, 0, template_rec);
193971bffdcdSAmine Khaldi                             MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_INFO, record);
194071bffdcdSAmine Khaldi                         }
194171bffdcdSAmine Khaldi                         template_rec = msi_get_error_message(package->db, MSIERR_INSTALLERROR);
194271bffdcdSAmine Khaldi                         MSI_RecordSetStringW(record, 0, template_rec);
194371bffdcdSAmine Khaldi                         MSI_ProcessMessageVerbatim(package, eMessageType, record);
1944*f4be6dc3SMikhail                         free(template_rec);
194571bffdcdSAmine Khaldi                         return 0;
194671bffdcdSAmine Khaldi                     }
194771bffdcdSAmine Khaldi                 }
194871bffdcdSAmine Khaldi             }
194971bffdcdSAmine Khaldi             else
195071bffdcdSAmine Khaldi                 template_rec = msi_dup_record_field(record, 0);
195171bffdcdSAmine Khaldi 
195271bffdcdSAmine Khaldi             template_prefix = msi_get_error_message(package->db, eMessageType >> 24);
1953*f4be6dc3SMikhail             if (!template_prefix) template_prefix = wcsdup(L"");
195471bffdcdSAmine Khaldi 
195571bffdcdSAmine Khaldi             if (!template_rec)
195671bffdcdSAmine Khaldi             {
195771bffdcdSAmine Khaldi                 /* always returns 0 */
195871bffdcdSAmine Khaldi                 MSI_RecordSetStringW(record, 0, template_prefix);
195971bffdcdSAmine Khaldi                 MSI_ProcessMessageVerbatim(package, eMessageType, record);
1960*f4be6dc3SMikhail                 free(template_prefix);
196171bffdcdSAmine Khaldi                 return 0;
196271bffdcdSAmine Khaldi             }
196371bffdcdSAmine Khaldi 
1964*f4be6dc3SMikhail             template = malloc((wcslen(template_rec) + wcslen(template_prefix) + 1) * sizeof(WCHAR));
1965*f4be6dc3SMikhail             if (!template)
1966*f4be6dc3SMikhail             {
1967*f4be6dc3SMikhail                 free(template_prefix);
1968*f4be6dc3SMikhail                 free(template_rec);
1969*f4be6dc3SMikhail                 return ERROR_OUTOFMEMORY;
1970*f4be6dc3SMikhail             }
197171bffdcdSAmine Khaldi 
1972958f1addSwinesync             lstrcpyW(template, template_prefix);
1973958f1addSwinesync             lstrcatW(template, template_rec);
197471bffdcdSAmine Khaldi             MSI_RecordSetStringW(record, 0, template);
197571bffdcdSAmine Khaldi 
1976*f4be6dc3SMikhail             free(template_prefix);
1977*f4be6dc3SMikhail             free(template_rec);
1978*f4be6dc3SMikhail             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);
1985*f4be6dc3SMikhail         free(template);
1986c2c66affSColin Finck 
1987*f4be6dc3SMikhail         free(package->LastAction);
1988*f4be6dc3SMikhail         free(package->LastActionTemplate);
198971bffdcdSAmine Khaldi         package->LastAction = msi_dup_record_field(record, 1);
1990*f4be6dc3SMikhail         if (!package->LastAction) package->LastAction = wcsdup(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;
1998*f4be6dc3SMikhail             WCHAR *template = malloc(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);
2002*f4be6dc3SMikhail             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);
2009*f4be6dc3SMikhail         free(template);
201071bffdcdSAmine Khaldi     }
2011c2c66affSColin Finck     break;
2012c2c66affSColin Finck     }
2013c2c66affSColin Finck 
201471bffdcdSAmine Khaldi     return MSI_ProcessMessageVerbatim(package, eMessageType, record);
2015c2c66affSColin Finck }
2016c2c66affSColin Finck 
MsiProcessMessage(MSIHANDLE hInstall,INSTALLMESSAGE eMessageType,MSIHANDLE hRecord)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 
MsiSetPropertyA(MSIHANDLE hInstall,LPCSTR szName,LPCSTR szValue)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:
2083*f4be6dc3SMikhail     free( szwName );
2084*f4be6dc3SMikhail     free( szwValue );
2085c2c66affSColin Finck 
2086c2c66affSColin Finck     return r;
2087c2c66affSColin Finck }
2088c2c66affSColin Finck 
msi_reset_source_folders(MSIPACKAGE * package)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     {
2095*f4be6dc3SMikhail         free( folder->ResolvedSource );
2096c2c66affSColin Finck         folder->ResolvedSource = NULL;
2097c2c66affSColin Finck     }
2098c2c66affSColin Finck }
2099c2c66affSColin Finck 
msi_set_property(MSIDATABASE * db,const WCHAR * name,const WCHAR * value,int len)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 
MsiSetPropertyW(MSIHANDLE hInstall,LPCWSTR szName,LPCWSTR szValue)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 
get_property_row(MSIDATABASE * db,const WCHAR * name)2183*f4be6dc3SMikhail static MSIRECORD *get_property_row( MSIDATABASE *db, const WCHAR *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;
2199*f4be6dc3SMikhail         buffer = malloc(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         {
2205*f4be6dc3SMikhail             free(buffer);
220671bffdcdSAmine Khaldi             return NULL;
2207f8b992f2SAmine Khaldi         }
220871bffdcdSAmine Khaldi         MSI_RecordSetStringW(row, 1, buffer);
2209*f4be6dc3SMikhail         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;
2217*f4be6dc3SMikhail         buffer = malloc(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         {
2223*f4be6dc3SMikhail             free(buffer);
222471bffdcdSAmine Khaldi             return NULL;
2225f8b992f2SAmine Khaldi         }
222671bffdcdSAmine Khaldi         MSI_RecordSetStringW(row, 1, buffer);
2227*f4be6dc3SMikhail         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 */
msi_get_property(MSIDATABASE * db,LPCWSTR szName,LPWSTR szValueBuf,LPDWORD pchValueBuf)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 
2258*f4be6dc3SMikhail     row = 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 
msi_dup_property(MSIDATABASE * db,LPCWSTR prop)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++;
2294*f4be6dc3SMikhail     str = malloc(sz * sizeof(WCHAR));
2295c2c66affSColin Finck     r = msi_get_property(db, prop, str, &sz);
2296c2c66affSColin Finck     if (r != ERROR_SUCCESS)
2297c2c66affSColin Finck     {
2298*f4be6dc3SMikhail         free(str);
2299c2c66affSColin Finck         str = NULL;
2300c2c66affSColin Finck     }
2301c2c66affSColin Finck 
2302c2c66affSColin Finck     return str;
2303c2c66affSColin Finck }
2304c2c66affSColin Finck 
msi_get_property_int(MSIDATABASE * db,LPCWSTR prop,int def)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;
2309*f4be6dc3SMikhail     free(str);
2310c2c66affSColin Finck     return val;
2311c2c66affSColin Finck }
2312c2c66affSColin Finck 
MsiGetPropertyA(MSIHANDLE hinst,const char * name,char * buf,DWORD * sz)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 
2373*f4be6dc3SMikhail     row = 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 
MsiGetPropertyW(MSIHANDLE hinst,const WCHAR * name,WCHAR * buf,DWORD * sz)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 
2436*f4be6dc3SMikhail     row = 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 
s_remote_GetActiveDatabase(MSIHANDLE hinst)2447a8bc3902Swinesync MSIHANDLE __cdecl s_remote_GetActiveDatabase(MSIHANDLE hinst)
2448b74b77aaSwinesync {
24497cc54a4fSwinesync     return MsiGetActiveDatabase(hinst);
2450c2c66affSColin Finck }
2451c2c66affSColin Finck 
s_remote_GetProperty(MSIHANDLE hinst,LPCWSTR property,LPWSTR * value,DWORD * size)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 
s_remote_SetProperty(MSIHANDLE hinst,LPCWSTR property,LPCWSTR value)2470a8bc3902Swinesync UINT __cdecl s_remote_SetProperty(MSIHANDLE hinst, LPCWSTR property, LPCWSTR value)
2471c2c66affSColin Finck {
24723431091cSwinesync     return MsiSetPropertyW(hinst, property, value);
2473c2c66affSColin Finck }
2474c2c66affSColin Finck 
s_remote_ProcessMessage(MSIHANDLE hinst,INSTALLMESSAGE message,struct wire_record * remote_rec)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 
s_remote_DoAction(MSIHANDLE hinst,LPCWSTR action)2490a8bc3902Swinesync UINT __cdecl s_remote_DoAction(MSIHANDLE hinst, LPCWSTR action)
2491c2c66affSColin Finck {
2492c65c209aSwinesync     return MsiDoActionW(hinst, action);
2493c2c66affSColin Finck }
2494c2c66affSColin Finck 
s_remote_Sequence(MSIHANDLE hinst,LPCWSTR table,int sequence)2495a8bc3902Swinesync UINT __cdecl s_remote_Sequence(MSIHANDLE hinst, LPCWSTR table, int sequence)
2496c2c66affSColin Finck {
249710abb6f6Swinesync     return MsiSequenceW(hinst, table, sequence);
2498c2c66affSColin Finck }
2499c2c66affSColin Finck 
s_remote_GetTargetPath(MSIHANDLE hinst,LPCWSTR folder,LPWSTR * value)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 
s_remote_SetTargetPath(MSIHANDLE hinst,LPCWSTR folder,LPCWSTR value)2517a8bc3902Swinesync UINT __cdecl s_remote_SetTargetPath(MSIHANDLE hinst, LPCWSTR folder, LPCWSTR value)
2518c2c66affSColin Finck {
2519a5e21001Swinesync     return MsiSetTargetPathW(hinst, folder, value);
2520c2c66affSColin Finck }
2521c2c66affSColin Finck 
s_remote_GetSourcePath(MSIHANDLE hinst,LPCWSTR folder,LPWSTR * value)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 
s_remote_GetMode(MSIHANDLE hinst,MSIRUNMODE mode)2539a8bc3902Swinesync BOOL __cdecl s_remote_GetMode(MSIHANDLE hinst, MSIRUNMODE mode)
2540c2c66affSColin Finck {
254183bbe8c8Swinesync     return MsiGetMode(hinst, mode);
2542c2c66affSColin Finck }
2543c2c66affSColin Finck 
s_remote_SetMode(MSIHANDLE hinst,MSIRUNMODE mode,BOOL state)2544a8bc3902Swinesync UINT __cdecl s_remote_SetMode(MSIHANDLE hinst, MSIRUNMODE mode, BOOL state)
2545c2c66affSColin Finck {
25465219367eSwinesync     return MsiSetMode(hinst, mode, state);
2547c2c66affSColin Finck }
2548c2c66affSColin Finck 
s_remote_GetFeatureState(MSIHANDLE hinst,LPCWSTR feature,INSTALLSTATE * installed,INSTALLSTATE * action)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 
s_remote_SetFeatureState(MSIHANDLE hinst,LPCWSTR feature,INSTALLSTATE state)2555a8bc3902Swinesync UINT __cdecl s_remote_SetFeatureState(MSIHANDLE hinst, LPCWSTR feature, INSTALLSTATE state)
2556c2c66affSColin Finck {
25575bbed507Swinesync     return MsiSetFeatureStateW(hinst, feature, state);
2558c2c66affSColin Finck }
2559c2c66affSColin Finck 
s_remote_GetComponentState(MSIHANDLE hinst,LPCWSTR component,INSTALLSTATE * installed,INSTALLSTATE * action)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 
s_remote_SetComponentState(MSIHANDLE hinst,LPCWSTR component,INSTALLSTATE state)2566a8bc3902Swinesync UINT __cdecl s_remote_SetComponentState(MSIHANDLE hinst, LPCWSTR component, INSTALLSTATE state)
2567c2c66affSColin Finck {
25681c8fdff2Swinesync     return MsiSetComponentStateW(hinst, component, state);
2569c2c66affSColin Finck }
2570c2c66affSColin Finck 
s_remote_GetLanguage(MSIHANDLE hinst)2571a8bc3902Swinesync LANGID __cdecl s_remote_GetLanguage(MSIHANDLE hinst)
2572c2c66affSColin Finck {
2573fdca3090Swinesync     return MsiGetLanguage(hinst);
2574c2c66affSColin Finck }
2575c2c66affSColin Finck 
s_remote_SetInstallLevel(MSIHANDLE hinst,int level)2576a8bc3902Swinesync UINT __cdecl s_remote_SetInstallLevel(MSIHANDLE hinst, int level)
2577c2c66affSColin Finck {
2578d20dc08fSwinesync     return MsiSetInstallLevel(hinst, level);
2579c2c66affSColin Finck }
2580c2c66affSColin Finck 
s_remote_FormatRecord(MSIHANDLE hinst,struct wire_record * remote_rec,LPWSTR * value)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 
s_remote_EvaluateCondition(MSIHANDLE hinst,LPCWSTR condition)2607a8bc3902Swinesync MSICONDITION __cdecl s_remote_EvaluateCondition(MSIHANDLE hinst, LPCWSTR condition)
2608c2c66affSColin Finck {
260903faa107Swinesync     return MsiEvaluateConditionW(hinst, condition);
2610c2c66affSColin Finck }
2611c2c66affSColin Finck 
s_remote_GetFeatureCost(MSIHANDLE hinst,LPCWSTR feature,MSICOSTTREE cost_tree,INSTALLSTATE state,INT * cost)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 
s_remote_EnumComponentCosts(MSIHANDLE hinst,LPCWSTR component,DWORD index,INSTALLSTATE state,LPWSTR drive,INT * cost,INT * temp)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 
msi_package_add_info(MSIPACKAGE * package,DWORD context,DWORD options,LPCWSTR property,LPWSTR value)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 
2635*f4be6dc3SMikhail     info = malloc(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;
2642*f4be6dc3SMikhail     info->value = wcsdup(value);
2643c2c66affSColin Finck     list_add_head(&package->sourcelist_info, &info->entry);
2644c2c66affSColin Finck 
2645c2c66affSColin Finck     return ERROR_SUCCESS;
2646c2c66affSColin Finck }
2647c2c66affSColin Finck 
msi_package_add_media_disk(MSIPACKAGE * package,DWORD context,DWORD options,DWORD disk_id,LPWSTR volume_label,LPWSTR disk_prompt)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 
2658*f4be6dc3SMikhail     disk = malloc(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;
2665*f4be6dc3SMikhail     disk->volume_label = wcsdup(volume_label);
2666*f4be6dc3SMikhail     disk->disk_prompt = wcsdup(disk_prompt);
2667c2c66affSColin Finck     list_add_head(&package->sourcelist_media, &disk->entry);
2668c2c66affSColin Finck 
2669c2c66affSColin Finck     return ERROR_SUCCESS;
2670c2c66affSColin Finck }
2671