mshtml: Use URI with stripped "wine:" part in NewURI call.
[wine] / dlls / msi / package.c
1 /*
2  * Implementation of the Microsoft Installer (msi.dll)
3  *
4  * Copyright 2004 Aric Stewart for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #define NONAMELESSUNION
22 #define NONAMELESSSTRUCT
23 #define COBJMACROS
24
25 #include <stdarg.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "winnls.h"
30 #include "shlwapi.h"
31 #include "wingdi.h"
32 #include "wine/debug.h"
33 #include "msi.h"
34 #include "msiquery.h"
35 #include "objidl.h"
36 #include "wincrypt.h"
37 #include "winuser.h"
38 #include "wininet.h"
39 #include "winver.h"
40 #include "urlmon.h"
41 #include "shlobj.h"
42 #include "wine/unicode.h"
43 #include "objbase.h"
44 #include "msidefs.h"
45 #include "sddl.h"
46
47 #include "msipriv.h"
48 #include "msiserver.h"
49
50 WINE_DEFAULT_DEBUG_CHANNEL(msi);
51
52 static void remove_tracked_tempfiles( MSIPACKAGE *package )
53 {
54     struct list *item, *cursor;
55
56     LIST_FOR_EACH_SAFE( item, cursor, &package->tempfiles )
57     {
58         MSITEMPFILE *temp = LIST_ENTRY( item, MSITEMPFILE, entry );
59
60         list_remove( &temp->entry );
61         TRACE("deleting temp file %s\n", debugstr_w( temp->Path ));
62         if (!DeleteFileW( temp->Path ))
63             ERR("failed to delete %s\n", debugstr_w( temp->Path ));
64         msi_free( temp->Path );
65         msi_free( temp );
66     }
67 }
68
69 static void free_feature( MSIFEATURE *feature )
70 {
71     struct list *item, *cursor;
72
73     LIST_FOR_EACH_SAFE( item, cursor, &feature->Children )
74     {
75         FeatureList *fl = LIST_ENTRY( item, FeatureList, entry );
76         list_remove( &fl->entry );
77         msi_free( fl );
78     }
79
80     LIST_FOR_EACH_SAFE( item, cursor, &feature->Components )
81     {
82         ComponentList *cl = LIST_ENTRY( item, ComponentList, entry );
83         list_remove( &cl->entry );
84         msi_free( cl );
85     }
86     msi_free( feature->Feature );
87     msi_free( feature->Feature_Parent );
88     msi_free( feature->Directory );
89     msi_free( feature->Description );
90     msi_free( feature->Title );
91     msi_free( feature );
92 }
93
94 static void free_extension( MSIEXTENSION *ext )
95 {
96     struct list *item, *cursor;
97
98     LIST_FOR_EACH_SAFE( item, cursor, &ext->verbs )
99     {
100         MSIVERB *verb = LIST_ENTRY( item, MSIVERB, entry );
101
102         list_remove( &verb->entry );
103         msi_free( verb->Verb );
104         msi_free( verb->Command );
105         msi_free( verb->Argument );
106         msi_free( verb );
107     }
108
109     msi_free( ext->Extension );
110     msi_free( ext->ProgIDText );
111     msi_free( ext );
112 }
113
114 static void free_package_structures( MSIPACKAGE *package )
115 {
116     INT i;
117     struct list *item, *cursor;
118
119     TRACE("Freeing package action data\n");
120
121     remove_tracked_tempfiles(package);
122
123     LIST_FOR_EACH_SAFE( item, cursor, &package->features )
124     {
125         MSIFEATURE *feature = LIST_ENTRY( item, MSIFEATURE, entry );
126         list_remove( &feature->entry );
127         free_feature( feature );
128     }
129
130     LIST_FOR_EACH_SAFE( item, cursor, &package->folders )
131     {
132         MSIFOLDER *folder = LIST_ENTRY( item, MSIFOLDER, entry );
133
134         list_remove( &folder->entry );
135         msi_free( folder->Parent );
136         msi_free( folder->Directory );
137         msi_free( folder->TargetDefault );
138         msi_free( folder->SourceLongPath );
139         msi_free( folder->SourceShortPath );
140         msi_free( folder->ResolvedTarget );
141         msi_free( folder->ResolvedSource );
142         msi_free( folder->Property );
143         msi_free( folder );
144     }
145
146     LIST_FOR_EACH_SAFE( item, cursor, &package->components )
147     {
148         MSICOMPONENT *comp = LIST_ENTRY( item, MSICOMPONENT, entry );
149
150         list_remove( &comp->entry );
151         msi_free( comp->Component );
152         msi_free( comp->ComponentId );
153         msi_free( comp->Directory );
154         msi_free( comp->Condition );
155         msi_free( comp->KeyPath );
156         msi_free( comp->FullKeypath );
157         msi_free( comp );
158     }
159
160     LIST_FOR_EACH_SAFE( item, cursor, &package->files )
161     {
162         MSIFILE *file = LIST_ENTRY( item, MSIFILE, entry );
163
164         list_remove( &file->entry );
165         msi_free( file->File );
166         msi_free( file->FileName );
167         msi_free( file->ShortName );
168         msi_free( file->LongName );
169         msi_free( file->Version );
170         msi_free( file->Language );
171         msi_free( file->TargetPath );
172         msi_free( file );
173     }
174
175     /* clean up extension, progid, class and verb structures */
176     LIST_FOR_EACH_SAFE( item, cursor, &package->classes )
177     {
178         MSICLASS *cls = LIST_ENTRY( item, MSICLASS, entry );
179
180         list_remove( &cls->entry );
181         msi_free( cls->clsid );
182         msi_free( cls->Context );
183         msi_free( cls->Description );
184         msi_free( cls->FileTypeMask );
185         msi_free( cls->IconPath );
186         msi_free( cls->DefInprocHandler );
187         msi_free( cls->DefInprocHandler32 );
188         msi_free( cls->Argument );
189         msi_free( cls->ProgIDText );
190         msi_free( cls );
191     }
192
193     LIST_FOR_EACH_SAFE( item, cursor, &package->extensions )
194     {
195         MSIEXTENSION *ext = LIST_ENTRY( item, MSIEXTENSION, entry );
196
197         list_remove( &ext->entry );
198         free_extension( ext );
199     }
200
201     LIST_FOR_EACH_SAFE( item, cursor, &package->progids )
202     {
203         MSIPROGID *progid = LIST_ENTRY( item, MSIPROGID, entry );
204
205         list_remove( &progid->entry );
206         msi_free( progid->ProgID );
207         msi_free( progid->Description );
208         msi_free( progid->IconPath );
209         msi_free( progid );
210     }
211
212     LIST_FOR_EACH_SAFE( item, cursor, &package->mimes )
213     {
214         MSIMIME *mt = LIST_ENTRY( item, MSIMIME, entry );
215
216         list_remove( &mt->entry );
217         msi_free( mt->clsid );
218         msi_free( mt->ContentType );
219         msi_free( mt );
220     }
221
222     LIST_FOR_EACH_SAFE( item, cursor, &package->appids )
223     {
224         MSIAPPID *appid = LIST_ENTRY( item, MSIAPPID, entry );
225
226         list_remove( &appid->entry );
227         msi_free( appid->AppID );
228         msi_free( appid->RemoteServerName );
229         msi_free( appid->LocalServer );
230         msi_free( appid->ServiceParameters );
231         msi_free( appid->DllSurrogate );
232         msi_free( appid );
233     }
234
235     LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_info )
236     {
237         MSISOURCELISTINFO *info = LIST_ENTRY( item, MSISOURCELISTINFO, entry );
238
239         list_remove( &info->entry );
240         msi_free( info->value );
241         msi_free( info );
242     }
243
244     LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_media )
245     {
246         MSIMEDIADISK *info = LIST_ENTRY( item, MSIMEDIADISK, entry );
247
248         list_remove( &info->entry );
249         msi_free( info->volume_label );
250         msi_free( info->disk_prompt );
251         msi_free( info );
252     }
253
254     if (package->script)
255     {
256         for (i = 0; i < TOTAL_SCRIPTS; i++)
257             msi_free_action_script( package, i );
258
259         for (i = 0; i < package->script->UniqueActionsCount; i++)
260             msi_free( package->script->UniqueActions[i] );
261
262         msi_free( package->script->UniqueActions );
263         msi_free( package->script );
264     }
265
266     if (package->patch)
267     {
268         msi_free( package->patch->patchcode );
269         msi_free( package->patch->transforms );
270         msi_free( package->patch );
271     }
272
273     msi_free( package->BaseURL );
274     msi_free( package->PackagePath );
275     msi_free( package->ProductCode );
276     msi_free( package->ActionFormat );
277     msi_free( package->LastAction );
278
279     /* cleanup control event subscriptions */
280     ControlEvent_CleanupSubscriptions( package );
281 }
282
283 static void MSI_FreePackage( MSIOBJECTHDR *arg)
284 {
285     MSIPACKAGE *package= (MSIPACKAGE*) arg;
286
287     if( package->dialog )
288         msi_dialog_destroy( package->dialog );
289
290     msiobj_release( &package->db->hdr );
291     free_package_structures(package);
292 }
293
294 static UINT create_temp_property_table(MSIPACKAGE *package)
295 {
296     MSIQUERY *view = NULL;
297     UINT rc;
298
299     static const WCHAR CreateSql[] = {
300        'C','R','E','A','T','E',' ','T','A','B','L','E',' ',
301        '`','_','P','r','o','p','e','r','t','y','`',' ','(',' ',
302        '`','_','P','r','o','p','e','r','t','y','`',' ',
303        'C','H','A','R','(','5','6',')',' ','N','O','T',' ','N','U','L','L',' ',
304        'T','E','M','P','O','R','A','R','Y',',',' ',
305        '`','V','a','l','u','e','`',' ','C','H','A','R','(','9','8',')',' ',
306        'N','O','T',' ','N','U','L','L',' ','T','E','M','P','O','R','A','R','Y',
307        ' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ',
308        '`','_','P','r','o','p','e','r','t','y','`',')',' ','H','O','L','D',0};
309
310     rc = MSI_DatabaseOpenViewW(package->db, CreateSql, &view);
311     if (rc != ERROR_SUCCESS)
312         return rc;
313
314     rc = MSI_ViewExecute(view, 0);
315     MSI_ViewClose(view);
316     msiobj_release(&view->hdr);
317     return rc;
318 }
319
320 UINT msi_clone_properties(MSIPACKAGE *package)
321 {
322     MSIQUERY *view = NULL;
323     UINT rc;
324
325     static const WCHAR Query[] = {
326        'S','E','L','E','C','T',' ','*',' ',
327        'F','R','O','M',' ','`','P','r','o','p','e','r','t','y','`',0};
328     static const WCHAR Insert[] = {
329        'I','N','S','E','R','T',' ','i','n','t','o',' ',
330        '`','_','P','r','o','p','e','r','t','y','`',' ',
331        '(','`','_','P','r','o','p','e','r','t','y','`',',',
332        '`','V','a','l','u','e','`',')',' ',
333        'V','A','L','U','E','S',' ','(','?',',','?',')',0};
334
335     /* clone the existing properties */
336     rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
337     if (rc != ERROR_SUCCESS)
338         return rc;
339
340     rc = MSI_ViewExecute(view, 0);
341     if (rc != ERROR_SUCCESS)
342     {
343         MSI_ViewClose(view);
344         msiobj_release(&view->hdr);
345         return rc;
346     }
347
348     while (1)
349     {
350         MSIRECORD *row;
351         MSIQUERY *view2;
352
353         rc = MSI_ViewFetch(view, &row);
354         if (rc != ERROR_SUCCESS)
355             break;
356
357         rc = MSI_DatabaseOpenViewW(package->db, Insert, &view2);
358         if (rc != ERROR_SUCCESS)
359         {
360             msiobj_release(&row->hdr);
361             continue;
362         }
363
364         MSI_ViewExecute(view2, row);
365         MSI_ViewClose(view2);
366         msiobj_release(&view2->hdr);
367         msiobj_release(&row->hdr);
368     }
369
370     MSI_ViewClose(view);
371     msiobj_release(&view->hdr);
372
373     return rc;
374 }
375
376 /*
377  * set_installed_prop
378  *
379  * Sets the "Installed" property to indicate that
380  *  the product is installed for the current user.
381  */
382 static UINT set_installed_prop( MSIPACKAGE *package )
383 {
384     HKEY hkey = 0;
385     UINT r;
386
387     r = MSIREG_OpenUninstallKey( package->ProductCode, &hkey, FALSE );
388     if (r == ERROR_SUCCESS)
389     {
390         RegCloseKey( hkey );
391         msi_set_property( package->db, szInstalled, szOne );
392     }
393
394     return r;
395 }
396
397 static UINT set_user_sid_prop( MSIPACKAGE *package )
398 {
399     SID_NAME_USE use;
400     LPWSTR user_name;
401     LPWSTR sid_str = NULL, dom = NULL;
402     DWORD size, dom_size;
403     PSID psid = NULL;
404     UINT r = ERROR_FUNCTION_FAILED;
405
406     size = 0;
407     GetUserNameW( NULL, &size );
408
409     user_name = msi_alloc( (size + 1) * sizeof(WCHAR) );
410     if (!user_name)
411         return ERROR_OUTOFMEMORY;
412
413     if (!GetUserNameW( user_name, &size ))
414         goto done;
415
416     size = 0;
417     dom_size = 0;
418     LookupAccountNameW( NULL, user_name, NULL, &size, NULL, &dom_size, &use );
419
420     psid = msi_alloc( size );
421     dom = msi_alloc( dom_size*sizeof (WCHAR) );
422     if (!psid || !dom)
423     {
424         r = ERROR_OUTOFMEMORY;
425         goto done;
426     }
427
428     if (!LookupAccountNameW( NULL, user_name, psid, &size, dom, &dom_size, &use ))
429         goto done;
430
431     if (!ConvertSidToStringSidW( psid, &sid_str ))
432         goto done;
433
434     r = msi_set_property( package->db, szUserSID, sid_str );
435
436 done:
437     LocalFree( sid_str );
438     msi_free( dom );
439     msi_free( psid );
440     msi_free( user_name );
441
442     return r;
443 }
444
445 static LPWSTR get_fusion_filename(MSIPACKAGE *package)
446 {
447     HKEY netsetup;
448     LONG res;
449     LPWSTR file = NULL;
450     DWORD index = 0, size;
451     WCHAR ver[MAX_PATH];
452     WCHAR name[MAX_PATH];
453     WCHAR windir[MAX_PATH];
454
455     static const WCHAR fusion[] = {'f','u','s','i','o','n','.','d','l','l',0};
456     static const WCHAR sub[] = {
457         'S','o','f','t','w','a','r','e','\\',
458         'M','i','c','r','o','s','o','f','t','\\',
459         'N','E','T',' ','F','r','a','m','e','w','o','r','k',' ','S','e','t','u','p','\\',
460         'N','D','P',0
461     };
462     static const WCHAR subdir[] = {
463         'M','i','c','r','o','s','o','f','t','.','N','E','T','\\',
464         'F','r','a','m','e','w','o','r','k','\\',0
465     };
466
467     res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, sub, 0, KEY_ENUMERATE_SUB_KEYS, &netsetup);
468     if (res != ERROR_SUCCESS)
469         return NULL;
470
471     GetWindowsDirectoryW(windir, MAX_PATH);
472
473     ver[0] = '\0';
474     size = MAX_PATH;
475     while (RegEnumKeyExW(netsetup, index, name, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
476     {
477         index++;
478
479         /* verify existence of fusion.dll .Net 3.0 does not install a new one */
480         if (lstrcmpW(ver, name) < 0)
481         {
482             LPWSTR check;
483             size = lstrlenW(windir) + lstrlenW(subdir) + lstrlenW(name) +lstrlenW(fusion) + 3;
484             check = msi_alloc(size * sizeof(WCHAR));
485
486             if (!check)
487             {
488                 msi_free(file);
489                 return NULL;
490             }
491
492             lstrcpyW(check, windir);
493             lstrcatW(check, szBackSlash);
494             lstrcatW(check, subdir);
495             lstrcatW(check, name);
496             lstrcatW(check, szBackSlash);
497             lstrcatW(check, fusion);
498
499             if(GetFileAttributesW(check) != INVALID_FILE_ATTRIBUTES)
500             {
501                 msi_free(file);
502                 file = check;
503                 lstrcpyW(ver, name);
504             }
505             else
506                 msi_free(check);
507         }
508     }
509
510     RegCloseKey(netsetup);
511     return file;
512 }
513
514 typedef struct tagLANGANDCODEPAGE
515 {
516   WORD wLanguage;
517   WORD wCodePage;
518 } LANGANDCODEPAGE;
519
520 static void set_msi_assembly_prop(MSIPACKAGE *package)
521 {
522     UINT val_len;
523     DWORD size, handle;
524     LPVOID version = NULL;
525     WCHAR buf[MAX_PATH];
526     LPWSTR fusion, verstr;
527     LANGANDCODEPAGE *translate;
528
529     static const WCHAR netasm[] = {
530         'M','s','i','N','e','t','A','s','s','e','m','b','l','y','S','u','p','p','o','r','t',0
531     };
532     static const WCHAR translation[] = {
533         '\\','V','a','r','F','i','l','e','I','n','f','o',
534         '\\','T','r','a','n','s','l','a','t','i','o','n',0
535     };
536     static const WCHAR verfmt[] = {
537         '\\','S','t','r','i','n','g','F','i','l','e','I','n','f','o',
538         '\\','%','0','4','x','%','0','4','x',
539         '\\','P','r','o','d','u','c','t','V','e','r','s','i','o','n',0
540     };
541
542     fusion = get_fusion_filename(package);
543     if (!fusion)
544         return;
545
546     size = GetFileVersionInfoSizeW(fusion, &handle);
547     if (!size) return;
548
549     version = msi_alloc(size);
550     if (!version) return;
551
552     if (!GetFileVersionInfoW(fusion, handle, size, version))
553         goto done;
554
555     if (!VerQueryValueW(version, translation, (LPVOID *)&translate, &val_len))
556         goto done;
557
558     sprintfW(buf, verfmt, translate[0].wLanguage, translate[0].wCodePage);
559
560     if (!VerQueryValueW(version, buf, (LPVOID *)&verstr, &val_len))
561         goto done;
562
563     if (!val_len || !verstr)
564         goto done;
565
566     msi_set_property(package->db, netasm, verstr);
567
568 done:
569     msi_free(fusion);
570     msi_free(version);
571 }
572
573 static VOID set_installer_properties(MSIPACKAGE *package)
574 {
575     WCHAR pth[MAX_PATH];
576     WCHAR *ptr;
577     OSVERSIONINFOEXW OSVersion;
578     MEMORYSTATUSEX msex;
579     DWORD verval, len;
580     WCHAR verstr[10], bufstr[20];
581     HDC dc;
582     HKEY hkey;
583     LPWSTR username, companyname;
584     SYSTEM_INFO sys_info;
585     SYSTEMTIME systemtime;
586     LANGID langid;
587
588     static const WCHAR CFF[] = 
589 {'C','o','m','m','o','n','F','i','l','e','s','F','o','l','d','e','r',0};
590     static const WCHAR PFF[] = 
591 {'P','r','o','g','r','a','m','F','i','l','e','s','F','o','l','d','e','r',0};
592     static const WCHAR CADF[] = 
593 {'C','o','m','m','o','n','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
594     static const WCHAR FaF[] = 
595 {'F','a','v','o','r','i','t','e','s','F','o','l','d','e','r',0};
596     static const WCHAR FoF[] = 
597 {'F','o','n','t','s','F','o','l','d','e','r',0};
598     static const WCHAR SendTF[] = 
599 {'S','e','n','d','T','o','F','o','l','d','e','r',0};
600     static const WCHAR SMF[] = 
601 {'S','t','a','r','t','M','e','n','u','F','o','l','d','e','r',0};
602     static const WCHAR StF[] = 
603 {'S','t','a','r','t','u','p','F','o','l','d','e','r',0};
604     static const WCHAR TemplF[] = 
605 {'T','e','m','p','l','a','t','e','F','o','l','d','e','r',0};
606     static const WCHAR DF[] = 
607 {'D','e','s','k','t','o','p','F','o','l','d','e','r',0};
608     static const WCHAR PMF[] = 
609 {'P','r','o','g','r','a','m','M','e','n','u','F','o','l','d','e','r',0};
610     static const WCHAR ATF[] = 
611 {'A','d','m','i','n','T','o','o','l','s','F','o','l','d','e','r',0};
612     static const WCHAR ADF[] = 
613 {'A','p','p','D','a','t','a','F','o','l','d','e','r',0};
614     static const WCHAR SF[] = 
615 {'S','y','s','t','e','m','F','o','l','d','e','r',0};
616     static const WCHAR SF16[] = 
617 {'S','y','s','t','e','m','1','6','F','o','l','d','e','r',0};
618     static const WCHAR LADF[] = 
619 {'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
620     static const WCHAR MPF[] = 
621 {'M','y','P','i','c','t','u','r','e','s','F','o','l','d','e','r',0};
622     static const WCHAR PF[] = 
623 {'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0};
624     static const WCHAR WF[] = 
625 {'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
626     static const WCHAR WV[] = 
627 {'W','i','n','d','o','w','s','V','o','l','u','m','e',0};
628     static const WCHAR TF[]=
629 {'T','e','m','p','F','o','l','d','e','r',0};
630     static const WCHAR szAdminUser[] =
631 {'A','d','m','i','n','U','s','e','r',0};
632     static const WCHAR szPriv[] =
633 {'P','r','i','v','i','l','e','g','e','d',0};
634     static const WCHAR v9x[] = { 'V','e','r','s','i','o','n','9','X',0 };
635     static const WCHAR vNT[] = { 'V','e','r','s','i','o','n','N','T',0 };
636     static const WCHAR szMsiNTProductType[] = { 'M','s','i','N','T','P','r','o','d','u','c','t','T','y','p','e',0 };
637     static const WCHAR szFormat[] = {'%','l','i',0};
638     static const WCHAR szWinBuild[] =
639 {'W','i','n','d','o','w','s','B','u','i','l','d', 0 };
640     static const WCHAR szSPL[] = 
641 {'S','e','r','v','i','c','e','P','a','c','k','L','e','v','e','l',0 };
642     static const WCHAR szSix[] = {'6',0 };
643
644     static const WCHAR szVersionMsi[] = { 'V','e','r','s','i','o','n','M','s','i',0 };
645     static const WCHAR szVersionDatabase[] = { 'V','e','r','s','i','o','n','D','a','t','a','b','a','s','e',0 };
646     static const WCHAR szPhysicalMemory[] = { 'P','h','y','s','i','c','a','l','M','e','m','o','r','y',0 };
647     static const WCHAR szFormat2[] = {'%','l','i','.','%','l','i',0};
648 /* Screen properties */
649     static const WCHAR szScreenX[] = {'S','c','r','e','e','n','X',0};
650     static const WCHAR szScreenY[] = {'S','c','r','e','e','n','Y',0};
651     static const WCHAR szColorBits[] = {'C','o','l','o','r','B','i','t','s',0};
652     static const WCHAR szIntFormat[] = {'%','d',0};
653     static const WCHAR szIntel[] = { 'I','n','t','e','l',0 };
654     static const WCHAR szUserInfo[] = {
655         'S','O','F','T','W','A','R','E','\\',
656         'M','i','c','r','o','s','o','f','t','\\',
657         'M','S',' ','S','e','t','u','p',' ','(','A','C','M','E',')','\\',
658         'U','s','e','r',' ','I','n','f','o',0
659     };
660     static const WCHAR szDefName[] = { 'D','e','f','N','a','m','e',0 };
661     static const WCHAR szDefCompany[] = { 'D','e','f','C','o','m','p','a','n','y',0 };
662     static const WCHAR szCurrentVersion[] = {
663         'S','O','F','T','W','A','R','E','\\',
664         'M','i','c','r','o','s','o','f','t','\\',
665         'W','i','n','d','o','w','s',' ','N','T','\\',
666         'C','u','r','r','e','n','t','V','e','r','s','i','o','n',0
667     };
668     static const WCHAR szRegisteredUser[] = {'R','e','g','i','s','t','e','r','e','d','O','w','n','e','r',0};
669     static const WCHAR szRegisteredOrg[] = {
670         'R','e','g','i','s','t','e','r','e','d','O','r','g','a','n','i','z','a','t','i','o','n',0
671     };
672     static const WCHAR szUSERNAME[] = {'U','S','E','R','N','A','M','E',0};
673     static const WCHAR szCOMPANYNAME[] = {'C','O','M','P','A','N','Y','N','A','M','E',0};
674     static const WCHAR szDate[] = {'D','a','t','e',0};
675     static const WCHAR szTime[] = {'T','i','m','e',0};
676     static const WCHAR szUserLangID[] = {'U','s','e','r','L','a','n','g','u','a','g','e','I','D',0};
677     static const WCHAR szSystemLangID[] = {'S','y','s','t','e','m','L','a','n','g','u','a','g','e','I','D',0};
678     static const WCHAR szProductState[] = {'P','r','o','d','u','c','t','S','t','a','t','e',0};
679     static const WCHAR szLogonUser[] = {'L','o','g','o','n','U','s','e','r',0};
680
681     /*
682      * Other things that probably should be set:
683      *
684      * ComputerName VirtualMemory
685      * ShellAdvSupport DefaultUIFont PackagecodeChanging
686      * CaptionHeight BorderTop BorderSide TextHeight
687      * RedirectedDllSupport
688      */
689
690     SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES_COMMON,NULL,0,pth);
691     strcatW(pth, szBackSlash);
692     msi_set_property(package->db, CFF, pth);
693
694     SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES,NULL,0,pth);
695     strcatW(pth, szBackSlash);
696     msi_set_property(package->db, PFF, pth);
697
698     SHGetFolderPathW(NULL,CSIDL_COMMON_APPDATA,NULL,0,pth);
699     strcatW(pth, szBackSlash);
700     msi_set_property(package->db, CADF, pth);
701
702     SHGetFolderPathW(NULL,CSIDL_FAVORITES,NULL,0,pth);
703     strcatW(pth, szBackSlash);
704     msi_set_property(package->db, FaF, pth);
705
706     SHGetFolderPathW(NULL,CSIDL_FONTS,NULL,0,pth);
707     strcatW(pth, szBackSlash);
708     msi_set_property(package->db, FoF, pth);
709
710     SHGetFolderPathW(NULL,CSIDL_SENDTO,NULL,0,pth);
711     strcatW(pth, szBackSlash);
712     msi_set_property(package->db, SendTF, pth);
713
714     SHGetFolderPathW(NULL,CSIDL_STARTMENU,NULL,0,pth);
715     strcatW(pth, szBackSlash);
716     msi_set_property(package->db, SMF, pth);
717
718     SHGetFolderPathW(NULL,CSIDL_STARTUP,NULL,0,pth);
719     strcatW(pth, szBackSlash);
720     msi_set_property(package->db, StF, pth);
721
722     SHGetFolderPathW(NULL,CSIDL_TEMPLATES,NULL,0,pth);
723     strcatW(pth, szBackSlash);
724     msi_set_property(package->db, TemplF, pth);
725
726     SHGetFolderPathW(NULL,CSIDL_DESKTOP,NULL,0,pth);
727     strcatW(pth, szBackSlash);
728     msi_set_property(package->db, DF, pth);
729
730     SHGetFolderPathW(NULL,CSIDL_PROGRAMS,NULL,0,pth);
731     strcatW(pth, szBackSlash);
732     msi_set_property(package->db, PMF, pth);
733
734     SHGetFolderPathW(NULL,CSIDL_ADMINTOOLS,NULL,0,pth);
735     strcatW(pth, szBackSlash);
736     msi_set_property(package->db, ATF, pth);
737
738     SHGetFolderPathW(NULL,CSIDL_APPDATA,NULL,0,pth);
739     strcatW(pth, szBackSlash);
740     msi_set_property(package->db, ADF, pth);
741
742     SHGetFolderPathW(NULL,CSIDL_SYSTEM,NULL,0,pth);
743     strcatW(pth, szBackSlash);
744     msi_set_property(package->db, SF, pth);
745     msi_set_property(package->db, SF16, pth);
746
747     SHGetFolderPathW(NULL,CSIDL_LOCAL_APPDATA,NULL,0,pth);
748     strcatW(pth, szBackSlash);
749     msi_set_property(package->db, LADF, pth);
750
751     SHGetFolderPathW(NULL,CSIDL_MYPICTURES,NULL,0,pth);
752     strcatW(pth, szBackSlash);
753     msi_set_property(package->db, MPF, pth);
754
755     SHGetFolderPathW(NULL,CSIDL_PERSONAL,NULL,0,pth);
756     strcatW(pth, szBackSlash);
757     msi_set_property(package->db, PF, pth);
758
759     SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
760     strcatW(pth, szBackSlash);
761     msi_set_property(package->db, WF, pth);
762     
763     /* Physical Memory is specified in MB. Using total amount. */
764     msex.dwLength = sizeof(msex);
765     GlobalMemoryStatusEx( &msex );
766     sprintfW( bufstr, szIntFormat, (int)(msex.ullTotalPhys/1024/1024));
767     msi_set_property(package->db, szPhysicalMemory, bufstr);
768
769     SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
770     ptr = strchrW(pth,'\\');
771     if (ptr)
772         *(ptr+1) = 0;
773     msi_set_property(package->db, WV, pth);
774     
775     GetTempPathW(MAX_PATH,pth);
776     msi_set_property(package->db, TF, pth);
777
778
779     /* in a wine environment the user is always admin and privileged */
780     msi_set_property(package->db, szAdminUser, szOne);
781     msi_set_property(package->db, szPriv, szOne);
782
783     /* set the os things */
784     OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
785     GetVersionExW((OSVERSIONINFOW *)&OSVersion);
786     verval = OSVersion.dwMinorVersion+OSVersion.dwMajorVersion*100;
787     sprintfW(verstr,szFormat,verval);
788     switch (OSVersion.dwPlatformId)
789     {
790         case VER_PLATFORM_WIN32_WINDOWS:    
791             msi_set_property(package->db, v9x, verstr);
792             break;
793         case VER_PLATFORM_WIN32_NT:
794             msi_set_property(package->db, vNT, verstr);
795             sprintfW(verstr,szFormat,OSVersion.wProductType);
796             msi_set_property(package->db, szMsiNTProductType, verstr);
797             break;
798     }
799     sprintfW(verstr,szFormat,OSVersion.dwBuildNumber);
800     msi_set_property(package->db, szWinBuild, verstr);
801     /* just fudge this */
802     msi_set_property(package->db, szSPL, szSix);
803
804     sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION);
805     msi_set_property( package->db, szVersionMsi, bufstr );
806     sprintfW( bufstr, szFormat, MSI_MAJORVERSION * 100);
807     msi_set_property( package->db, szVersionDatabase, bufstr );
808
809     GetSystemInfo( &sys_info );
810     if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
811     {
812         sprintfW( bufstr, szIntFormat, sys_info.wProcessorLevel );
813         msi_set_property( package->db, szIntel, bufstr );
814     }
815
816     /* Screen properties. */
817     dc = GetDC(0);
818     sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, HORZRES ) );
819     msi_set_property( package->db, szScreenX, bufstr );
820     sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, VERTRES ));
821     msi_set_property( package->db, szScreenY, bufstr );
822     sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, BITSPIXEL ));
823     msi_set_property( package->db, szColorBits, bufstr );
824     ReleaseDC(0, dc);
825
826     /* USERNAME and COMPANYNAME */
827     username = msi_dup_property( package->db, szUSERNAME );
828     companyname = msi_dup_property( package->db, szCOMPANYNAME );
829
830     if ((!username || !companyname) &&
831         RegOpenKeyW( HKEY_CURRENT_USER, szUserInfo, &hkey ) == ERROR_SUCCESS)
832     {
833         if (!username &&
834             (username = msi_reg_get_val_str( hkey, szDefName )))
835             msi_set_property( package->db, szUSERNAME, username );
836         if (!companyname &&
837             (companyname = msi_reg_get_val_str( hkey, szDefCompany )))
838             msi_set_property( package->db, szCOMPANYNAME, companyname );
839         CloseHandle( hkey );
840     }
841     if ((!username || !companyname) &&
842         RegOpenKeyW( HKEY_LOCAL_MACHINE, szCurrentVersion, &hkey ) == ERROR_SUCCESS)
843     {
844         if (!username &&
845             (username = msi_reg_get_val_str( hkey, szRegisteredUser )))
846             msi_set_property( package->db, szUSERNAME, username );
847         if (!companyname &&
848             (companyname = msi_reg_get_val_str( hkey, szRegisteredOrg )))
849             msi_set_property( package->db, szCOMPANYNAME, companyname );
850         CloseHandle( hkey );
851     }
852     msi_free( username );
853     msi_free( companyname );
854
855     if ( set_user_sid_prop( package ) != ERROR_SUCCESS)
856         ERR("Failed to set the UserSID property\n");
857
858     /* Date and time properties */
859     GetSystemTime( &systemtime );
860     if (GetDateFormatW( LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systemtime,
861                         NULL, bufstr, sizeof(bufstr)/sizeof(bufstr[0]) ))
862         msi_set_property( package->db, szDate, bufstr );
863     else
864         ERR("Couldn't set Date property: GetDateFormat failed with error %d\n", GetLastError());
865
866     if (GetTimeFormatW( LOCALE_USER_DEFAULT,
867                         TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER,
868                         &systemtime, NULL, bufstr,
869                         sizeof(bufstr)/sizeof(bufstr[0]) ))
870         msi_set_property( package->db, szTime, bufstr );
871     else
872         ERR("Couldn't set Time property: GetTimeFormat failed with error %d\n", GetLastError());
873
874     set_msi_assembly_prop( package );
875
876     langid = GetUserDefaultLangID();
877     sprintfW(bufstr, szIntFormat, langid);
878     msi_set_property( package->db, szUserLangID, bufstr );
879
880     langid = GetSystemDefaultLangID();
881     sprintfW(bufstr, szIntFormat, langid);
882     msi_set_property( package->db, szSystemLangID, bufstr );
883
884     sprintfW(bufstr, szIntFormat, MsiQueryProductStateW(package->ProductCode));
885     msi_set_property( package->db, szProductState, bufstr );
886
887     len = 0;
888     if (!GetUserNameW( NULL, &len ) && GetLastError() == ERROR_MORE_DATA)
889     {
890         WCHAR *username;
891         if ((username = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
892         {
893             if (GetUserNameW( username, &len ))
894                 msi_set_property( package->db, szLogonUser, username );
895             HeapFree( GetProcessHeap(), 0, username );
896         }
897     }
898 }
899
900 static UINT msi_load_summary_properties( MSIPACKAGE *package )
901 {
902     UINT rc;
903     MSIHANDLE suminfo;
904     MSIHANDLE hdb = alloc_msihandle( &package->db->hdr );
905     INT count;
906     DWORD len;
907     LPWSTR package_code;
908     static const WCHAR szPackageCode[] = {
909         'P','a','c','k','a','g','e','C','o','d','e',0};
910
911     if (!hdb) {
912         ERR("Unable to allocate handle\n");
913         return ERROR_OUTOFMEMORY;
914     }
915
916     rc = MsiGetSummaryInformationW( hdb, NULL, 0, &suminfo );
917     MsiCloseHandle(hdb);
918     if (rc != ERROR_SUCCESS)
919     {
920         ERR("Unable to open Summary Information\n");
921         return rc;
922     }
923
924     rc = MsiSummaryInfoGetPropertyW( suminfo, PID_PAGECOUNT, NULL,
925                                      &count, NULL, NULL, NULL );
926     if (rc != ERROR_SUCCESS)
927     {
928         WARN("Unable to query page count: %d\n", rc);
929         goto done;
930     }
931
932     /* load package code property */
933     len = 0;
934     rc = MsiSummaryInfoGetPropertyW( suminfo, PID_REVNUMBER, NULL,
935                                      NULL, NULL, NULL, &len );
936     if (rc != ERROR_MORE_DATA)
937     {
938         WARN("Unable to query revision number: %d\n", rc);
939         rc = ERROR_FUNCTION_FAILED;
940         goto done;
941     }
942
943     len++;
944     package_code = msi_alloc( len * sizeof(WCHAR) );
945     rc = MsiSummaryInfoGetPropertyW( suminfo, PID_REVNUMBER, NULL,
946                                      NULL, NULL, package_code, &len );
947     if (rc != ERROR_SUCCESS)
948     {
949         WARN("Unable to query rev number: %d\n", rc);
950         goto done;
951     }
952
953     msi_set_property( package->db, szPackageCode, package_code );
954     msi_free( package_code );
955
956     /* load package attributes */
957     count = 0;
958     MsiSummaryInfoGetPropertyW( suminfo, PID_WORDCOUNT, NULL,
959                                 &count, NULL, NULL, NULL );
960     package->WordCount = count;
961
962 done:
963     MsiCloseHandle(suminfo);
964     return rc;
965 }
966
967 static MSIPACKAGE *msi_alloc_package( void )
968 {
969     MSIPACKAGE *package;
970
971     package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE),
972                                MSI_FreePackage );
973     if( package )
974     {
975         list_init( &package->components );
976         list_init( &package->features );
977         list_init( &package->files );
978         list_init( &package->tempfiles );
979         list_init( &package->folders );
980         list_init( &package->subscriptions );
981         list_init( &package->appids );
982         list_init( &package->classes );
983         list_init( &package->mimes );
984         list_init( &package->extensions );
985         list_init( &package->progids );
986         list_init( &package->RunningActions );
987         list_init( &package->sourcelist_info );
988         list_init( &package->sourcelist_media );
989     }
990
991     return package;
992 }
993
994 static UINT msi_load_admin_properties(MSIPACKAGE *package)
995 {
996     BYTE *data;
997     UINT r, sz;
998
999     static const WCHAR stmname[] = {'A','d','m','i','n','P','r','o','p','e','r','t','i','e','s',0};
1000
1001     r = read_stream_data(package->db->storage, stmname, FALSE, &data, &sz);
1002     if (r != ERROR_SUCCESS)
1003         return r;
1004
1005     r = msi_parse_command_line(package, (WCHAR *)data, TRUE);
1006
1007     msi_free(data);
1008     return r;
1009 }
1010
1011 static void adjust_allusers_property( MSIPACKAGE *package )
1012 {
1013     /* FIXME: this should depend on the user's privileges */
1014     if (msi_get_property_int( package->db, szAllUsers, 0 ) == 2)
1015     {
1016         TRACE("resetting ALLUSERS property from 2 to 1\n");
1017         msi_set_property( package->db, szAllUsers, szOne );
1018     }
1019 }
1020
1021 MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url )
1022 {
1023     static const WCHAR szLevel[] = { 'U','I','L','e','v','e','l',0 };
1024     static const WCHAR szpi[] = {'%','i',0};
1025     MSIPACKAGE *package;
1026     WCHAR uilevel[10];
1027     UINT r;
1028
1029     TRACE("%p\n", db);
1030
1031     package = msi_alloc_package();
1032     if (package)
1033     {
1034         msiobj_addref( &db->hdr );
1035         package->db = db;
1036
1037         package->WordCount = 0;
1038         package->PackagePath = strdupW( db->path );
1039         package->BaseURL = strdupW( base_url );
1040
1041         create_temp_property_table( package );
1042         msi_clone_properties( package );
1043
1044         package->ProductCode = msi_dup_property( package->db, szProductCode );
1045         set_installed_prop( package );
1046         set_installer_properties( package );
1047
1048         sprintfW(uilevel,szpi,gUILevel);
1049         msi_set_property(package->db, szLevel, uilevel);
1050
1051         r = msi_load_summary_properties( package );
1052         if (r != ERROR_SUCCESS)
1053         {
1054             msiobj_release( &package->hdr );
1055             return NULL;
1056         }
1057
1058         if (package->WordCount & msidbSumInfoSourceTypeAdminImage)
1059             msi_load_admin_properties( package );
1060
1061         adjust_allusers_property( package );
1062     }
1063
1064     return package;
1065 }
1066
1067 /*
1068  * copy_package_to_temp   [internal]
1069  *
1070  * copy the msi file to a temp file to prevent locking a CD
1071  * with a multi disc install 
1072  *
1073  * FIXME: I think this is wrong, and instead of copying the package,
1074  *        we should read all the tables to memory, then open the
1075  *        database to read binary streams on demand.
1076  */ 
1077 static UINT copy_package_to_temp( LPCWSTR szPackage, LPWSTR filename )
1078 {
1079     WCHAR path[MAX_PATH];
1080
1081     GetTempPathW( MAX_PATH, path );
1082     GetTempFileNameW( path, szMsi, 0, filename );
1083
1084     if( !CopyFileW( szPackage, filename, FALSE ) )
1085     {
1086         UINT error = GetLastError();
1087         ERR("failed to copy package %s to %s (%u)\n", debugstr_w(szPackage), debugstr_w(filename), error);
1088         DeleteFileW( filename );
1089         return error;
1090     }
1091
1092     return ERROR_SUCCESS;
1093 }
1094
1095 UINT msi_download_file( LPCWSTR szUrl, LPWSTR filename )
1096 {
1097     LPINTERNET_CACHE_ENTRY_INFOW cache_entry;
1098     DWORD size = 0;
1099     HRESULT hr;
1100
1101     /* call will always fail, becase size is 0,
1102      * but will return ERROR_FILE_NOT_FOUND first
1103      * if the file doesn't exist
1104      */
1105     GetUrlCacheEntryInfoW( szUrl, NULL, &size );
1106     if ( GetLastError() != ERROR_FILE_NOT_FOUND )
1107     {
1108         cache_entry = HeapAlloc( GetProcessHeap(), 0, size );
1109         if ( !GetUrlCacheEntryInfoW( szUrl, cache_entry, &size ) )
1110         {
1111             UINT error = GetLastError();
1112             HeapFree( GetProcessHeap(), 0, cache_entry );
1113             return error;
1114         }
1115
1116         lstrcpyW( filename, cache_entry->lpszLocalFileName );
1117         HeapFree( GetProcessHeap(), 0, cache_entry );
1118         return ERROR_SUCCESS;
1119     }
1120
1121     hr = URLDownloadToCacheFileW( NULL, szUrl, filename, MAX_PATH, 0, NULL );
1122     if ( FAILED(hr) )
1123     {
1124         WARN("failed to download %s to cache file\n", debugstr_w(szUrl));
1125         return ERROR_FUNCTION_FAILED;
1126     }
1127
1128     return ERROR_SUCCESS;
1129 }
1130
1131 static UINT msi_get_local_package_name( LPWSTR path )
1132 {
1133     static const WCHAR szInstaller[] = {
1134         '\\','I','n','s','t','a','l','l','e','r','\\',0};
1135     static const WCHAR fmt[] = { '%','x','.','m','s','i',0};
1136     DWORD time, len, i;
1137     HANDLE handle;
1138
1139     time = GetTickCount();
1140     GetWindowsDirectoryW( path, MAX_PATH );
1141     strcatW( path, szInstaller );
1142     CreateDirectoryW( path, NULL );
1143
1144     len = strlenW(path);
1145     for (i = 0; i < 0x10000; i++)
1146     {
1147         snprintfW( &path[len], MAX_PATH - len, fmt, (time + i)&0xffff );
1148         handle = CreateFileW( path, GENERIC_WRITE, 0, NULL,
1149                               CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
1150         if (handle != INVALID_HANDLE_VALUE)
1151         {
1152             CloseHandle(handle);
1153             break;
1154         }
1155         if (GetLastError() != ERROR_FILE_EXISTS &&
1156             GetLastError() != ERROR_SHARING_VIOLATION)
1157             return ERROR_FUNCTION_FAILED;
1158     }
1159
1160     return ERROR_SUCCESS;
1161 }
1162
1163 UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
1164 {
1165     static const WCHAR OriginalDatabase[] =
1166         {'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
1167     static const WCHAR Database[] = {'D','A','T','A','B','A','S','E',0};
1168     MSIDATABASE *db = NULL;
1169     MSIPACKAGE *package;
1170     MSIHANDLE handle;
1171     LPWSTR ptr, base_url = NULL;
1172     UINT r;
1173     WCHAR temppath[MAX_PATH], localfile[MAX_PATH], cachefile[MAX_PATH];
1174     LPCWSTR file = szPackage;
1175
1176     TRACE("%s %p\n", debugstr_w(szPackage), pPackage);
1177
1178     if( szPackage[0] == '#' )
1179     {
1180         handle = atoiW(&szPackage[1]);
1181         db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE );
1182         if( !db )
1183         {
1184             IWineMsiRemoteDatabase *remote_database;
1185
1186             remote_database = (IWineMsiRemoteDatabase *)msi_get_remote( handle );
1187             if ( !remote_database )
1188                 return ERROR_INVALID_HANDLE;
1189
1190             IWineMsiRemoteDatabase_Release( remote_database );
1191             WARN("MsiOpenPackage not allowed during a custom action!\n");
1192
1193             return ERROR_FUNCTION_FAILED;
1194         }
1195     }
1196     else
1197     {
1198         if ( UrlIsW( szPackage, URLIS_URL ) )
1199         {
1200             r = msi_download_file( szPackage, cachefile );
1201             if ( r != ERROR_SUCCESS )
1202                 return r;
1203
1204             r = copy_package_to_temp( cachefile, temppath );
1205             if ( r != ERROR_SUCCESS )
1206                 return r;
1207
1208             file = temppath;
1209
1210             base_url = strdupW( szPackage );
1211             if ( !base_url )
1212                 return ERROR_OUTOFMEMORY;
1213
1214             ptr = strrchrW( base_url, '/' );
1215             if (ptr) *(ptr + 1) = '\0';
1216         }
1217         else
1218         {
1219             r = copy_package_to_temp( szPackage, temppath );
1220             if ( r != ERROR_SUCCESS )
1221                 return r;
1222
1223             file = temppath;
1224         }
1225
1226         r = msi_get_local_package_name( localfile );
1227         if (r != ERROR_SUCCESS)
1228             return r;
1229
1230         TRACE("Copying to local package %s\n", debugstr_w(localfile));
1231
1232         if (!CopyFileW( file, localfile, FALSE ))
1233         {
1234             ERR("Unable to copy package (%s -> %s) (error %u)\n",
1235                 debugstr_w(file), debugstr_w(localfile), GetLastError());
1236             return GetLastError();
1237         }
1238
1239         TRACE("Opening relocated package %s\n", debugstr_w( file ));
1240
1241         /* transforms that add binary streams require that we open the database
1242          * read/write, which is safe because we always create a copy that is thrown
1243          * away when we're done.
1244          */
1245         r = MSI_OpenDatabaseW( file, MSIDBOPEN_DIRECT, &db );
1246         if( r != ERROR_SUCCESS )
1247         {
1248             if (file != szPackage)
1249                 DeleteFileW( file );
1250
1251             if (GetFileAttributesW(szPackage) == INVALID_FILE_ATTRIBUTES)
1252                 return ERROR_FILE_NOT_FOUND;
1253
1254             return r;
1255         }
1256
1257         db->localfile = strdupW( localfile );
1258     }
1259
1260     package = MSI_CreatePackage( db, base_url );
1261     msi_free( base_url );
1262     msiobj_release( &db->hdr );
1263     if( !package )
1264     {
1265         if (file != szPackage)
1266             DeleteFileW( file );
1267
1268         return ERROR_INSTALL_PACKAGE_INVALID;
1269     }
1270
1271     if( file != szPackage )
1272         track_tempfile( package, file );
1273
1274     msi_set_property( package->db, Database, db->path );
1275
1276     if( UrlIsW( szPackage, URLIS_URL ) )
1277         msi_set_property( package->db, OriginalDatabase, szPackage );
1278     else if( szPackage[0] == '#' )
1279         msi_set_property( package->db, OriginalDatabase, db->path );
1280     else
1281     {
1282         WCHAR fullpath[MAX_PATH];
1283
1284         GetFullPathNameW( szPackage, MAX_PATH, fullpath, NULL );
1285         msi_set_property( package->db, OriginalDatabase, fullpath );
1286     }
1287
1288     package->script = msi_alloc_zero( sizeof(MSISCRIPT) );
1289     *pPackage = package;
1290
1291     return ERROR_SUCCESS;
1292 }
1293
1294 UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
1295 {
1296     MSIPACKAGE *package = NULL;
1297     UINT ret;
1298
1299     TRACE("%s %08x %p\n", debugstr_w(szPackage), dwOptions, phPackage );
1300
1301     if( !szPackage || !phPackage )
1302         return ERROR_INVALID_PARAMETER;
1303
1304     if ( !*szPackage )
1305     {
1306         FIXME("Should create an empty database and package\n");
1307         return ERROR_FUNCTION_FAILED;
1308     }
1309
1310     if( dwOptions )
1311         FIXME("dwOptions %08x not supported\n", dwOptions);
1312
1313     ret = MSI_OpenPackageW( szPackage, &package );
1314     if( ret == ERROR_SUCCESS )
1315     {
1316         *phPackage = alloc_msihandle( &package->hdr );
1317         if (! *phPackage)
1318             ret = ERROR_NOT_ENOUGH_MEMORY;
1319         msiobj_release( &package->hdr );
1320     }
1321
1322     return ret;
1323 }
1324
1325 UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
1326 {
1327     return MsiOpenPackageExW( szPackage, 0, phPackage );
1328 }
1329
1330 UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
1331 {
1332     LPWSTR szwPack = NULL;
1333     UINT ret;
1334
1335     if( szPackage )
1336     {
1337         szwPack = strdupAtoW( szPackage );
1338         if( !szwPack )
1339             return ERROR_OUTOFMEMORY;
1340     }
1341
1342     ret = MsiOpenPackageExW( szwPack, dwOptions, phPackage );
1343
1344     msi_free( szwPack );
1345
1346     return ret;
1347 }
1348
1349 UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
1350 {
1351     return MsiOpenPackageExA( szPackage, 0, phPackage );
1352 }
1353
1354 MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
1355 {
1356     MSIPACKAGE *package;
1357     MSIHANDLE handle = 0;
1358     IUnknown *remote_unk;
1359     IWineMsiRemotePackage *remote_package;
1360
1361     TRACE("(%d)\n",hInstall);
1362
1363     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
1364     if( package)
1365     {
1366         handle = alloc_msihandle( &package->db->hdr );
1367         msiobj_release( &package->hdr );
1368     }
1369     else if ((remote_unk = msi_get_remote(hInstall)))
1370     {
1371         if (IUnknown_QueryInterface(remote_unk, &IID_IWineMsiRemotePackage,
1372                                         (LPVOID *)&remote_package) == S_OK)
1373         {
1374             IWineMsiRemotePackage_GetActiveDatabase(remote_package, &handle);
1375             IWineMsiRemotePackage_Release(remote_package);
1376         }
1377         else
1378         {
1379             WARN("remote handle %d is not a package\n", hInstall);
1380         }
1381         IUnknown_Release(remote_unk);
1382     }
1383
1384     return handle;
1385 }
1386
1387 INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType,
1388                                MSIRECORD *record)
1389 {
1390     static const WCHAR szActionData[] =
1391         {'A','c','t','i','o','n','D','a','t','a',0};
1392     static const WCHAR szSetProgress[] =
1393         {'S','e','t','P','r','o','g','r','e','s','s',0};
1394     static const WCHAR szActionText[] =
1395         {'A','c','t','i','o','n','T','e','x','t',0};
1396     DWORD log_type = 0;
1397     LPWSTR message;
1398     DWORD sz;
1399     DWORD total_size = 0;
1400     INT i;
1401     INT rc;
1402     char *msg;
1403     int len;
1404
1405     TRACE("%x\n", eMessageType);
1406     rc = 0;
1407
1408     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ERROR)
1409         log_type |= INSTALLLOGMODE_ERROR;
1410     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_WARNING)
1411         log_type |= INSTALLLOGMODE_WARNING;
1412     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_USER)
1413         log_type |= INSTALLLOGMODE_USER;
1414     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INFO)
1415         log_type |= INSTALLLOGMODE_INFO;
1416     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA)
1417         log_type |= INSTALLLOGMODE_COMMONDATA;
1418     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART)
1419         log_type |= INSTALLLOGMODE_ACTIONSTART;
1420     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONDATA)
1421         log_type |= INSTALLLOGMODE_ACTIONDATA;
1422     /* just a guess */
1423     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_PROGRESS)
1424         log_type |= 0x800;
1425
1426     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART)
1427     {
1428         static const WCHAR template_s[]=
1429             {'A','c','t','i','o','n',' ','%','s',':',' ','%','s','.',' ',0};
1430         static const WCHAR format[] = 
1431             {'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0};
1432         WCHAR timet[0x100];
1433         LPCWSTR action_text, action;
1434         LPWSTR deformatted = NULL;
1435
1436         GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, format, timet, 0x100);
1437
1438         action = MSI_RecordGetString(record, 1);
1439         action_text = MSI_RecordGetString(record, 2);
1440
1441         if (!action || !action_text)
1442             return IDOK;
1443
1444         deformat_string(package, action_text, &deformatted);
1445
1446         len = strlenW(timet) + strlenW(action) + strlenW(template_s);
1447         if (deformatted)
1448             len += strlenW(deformatted);
1449         message = msi_alloc(len*sizeof(WCHAR));
1450         sprintfW(message, template_s, timet, action);
1451         if (deformatted)
1452             strcatW(message, deformatted);
1453         msi_free(deformatted);
1454     }
1455     else
1456     {
1457         INT msg_field=1;
1458         message = msi_alloc(1*sizeof (WCHAR));
1459         message[0]=0;
1460         msg_field = MSI_RecordGetFieldCount(record);
1461         for (i = 1; i <= msg_field; i++)
1462         {
1463             LPWSTR tmp;
1464             WCHAR number[3];
1465             static const WCHAR format[] = { '%','i',':',' ',0};
1466             sz = 0;
1467             MSI_RecordGetStringW(record,i,NULL,&sz);
1468             sz+=4;
1469             total_size+=sz*sizeof(WCHAR);
1470             tmp = msi_alloc(sz*sizeof(WCHAR));
1471             message = msi_realloc(message,total_size*sizeof (WCHAR));
1472
1473             MSI_RecordGetStringW(record,i,tmp,&sz);
1474
1475             if (msg_field > 1)
1476             {
1477                 sprintfW(number,format,i);
1478                 strcatW(message,number);
1479             }
1480             strcatW(message,tmp);
1481             if (msg_field > 1)
1482                 strcatW(message, szSpace);
1483
1484             msi_free(tmp);
1485         }
1486     }
1487
1488     TRACE("%p %p %p %x %x %s\n", gUIHandlerA, gUIHandlerW, gUIHandlerRecord,
1489           gUIFilter, log_type, debugstr_w(message));
1490
1491     /* convert it to ASCII */
1492     len = WideCharToMultiByte( CP_ACP, 0, message, -1, NULL, 0, NULL, NULL );
1493     msg = msi_alloc( len );
1494     WideCharToMultiByte( CP_ACP, 0, message, -1, msg, len, NULL, NULL );
1495
1496     if (gUIHandlerW && (gUIFilter & log_type))
1497     {
1498         rc = gUIHandlerW( gUIContext, eMessageType, message );
1499     }
1500     else if (gUIHandlerA && (gUIFilter & log_type))
1501     {
1502         rc = gUIHandlerA( gUIContext, eMessageType, msg );
1503     }
1504     else if (gUIHandlerRecord && (gUIFilter & log_type))
1505     {
1506         MSIHANDLE rec = MsiCreateRecord( 1 );
1507         MsiRecordSetStringW( rec, 0, message );
1508         rc = gUIHandlerRecord( gUIContext, eMessageType, rec );
1509         MsiCloseHandle( rec );
1510     }
1511
1512     if ((!rc) && (gszLogFile[0]) && !((eMessageType & 0xff000000) ==
1513                                       INSTALLMESSAGE_PROGRESS))
1514     {
1515         DWORD write;
1516         HANDLE log_file = CreateFileW(gszLogFile,GENERIC_WRITE, 0, NULL,
1517                                   OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1518
1519         if (log_file != INVALID_HANDLE_VALUE)
1520         {
1521             SetFilePointer(log_file,0, NULL, FILE_END);
1522             WriteFile(log_file,msg,strlen(msg),&write,NULL);
1523             WriteFile(log_file,"\n",1,&write,NULL);
1524             CloseHandle(log_file);
1525         }
1526     }
1527     msi_free( msg );
1528     msi_free( message );
1529
1530     switch (eMessageType & 0xff000000)
1531     {
1532     case INSTALLMESSAGE_ACTIONDATA:
1533         /* FIXME: format record here instead of in ui_actiondata to get the
1534          * correct action data for external scripts */
1535         ControlEvent_FireSubscribedEvent(package, szActionData, record);
1536         break;
1537     case INSTALLMESSAGE_ACTIONSTART:
1538     {
1539         MSIRECORD *uirow;
1540         LPWSTR deformated;
1541         LPCWSTR action_text = MSI_RecordGetString(record, 2);
1542
1543         deformat_string(package, action_text, &deformated);
1544         uirow = MSI_CreateRecord(1);
1545         MSI_RecordSetStringW(uirow, 1, deformated);
1546         TRACE("INSTALLMESSAGE_ACTIONSTART: %s\n", debugstr_w(deformated));
1547         msi_free(deformated);
1548
1549         ControlEvent_FireSubscribedEvent(package, szActionText, uirow);
1550
1551         msiobj_release(&uirow->hdr);
1552         break;
1553     }
1554     case INSTALLMESSAGE_PROGRESS:
1555         ControlEvent_FireSubscribedEvent(package, szSetProgress, record);
1556         break;
1557     }
1558
1559     return ERROR_SUCCESS;
1560 }
1561
1562 INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
1563                               MSIHANDLE hRecord)
1564 {
1565     UINT ret = ERROR_INVALID_HANDLE;
1566     MSIPACKAGE *package = NULL;
1567     MSIRECORD *record = NULL;
1568
1569     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
1570     if( !package )
1571     {
1572         HRESULT hr;
1573         IWineMsiRemotePackage *remote_package;
1574
1575         remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
1576         if (!remote_package)
1577             return ERROR_INVALID_HANDLE;
1578
1579         hr = IWineMsiRemotePackage_ProcessMessage( remote_package, eMessageType, hRecord );
1580
1581         IWineMsiRemotePackage_Release( remote_package );
1582
1583         if (FAILED(hr))
1584         {
1585             if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1586                 return HRESULT_CODE(hr);
1587
1588             return ERROR_FUNCTION_FAILED;
1589         }
1590
1591         return ERROR_SUCCESS;
1592     }
1593
1594     record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD );
1595     if( !record )
1596         goto out;
1597
1598     ret = MSI_ProcessMessage( package, eMessageType, record );
1599
1600 out:
1601     msiobj_release( &package->hdr );
1602     if( record )
1603         msiobj_release( &record->hdr );
1604
1605     return ret;
1606 }
1607
1608 /* property code */
1609
1610 UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue )
1611 {
1612     LPWSTR szwName = NULL, szwValue = NULL;
1613     UINT r = ERROR_OUTOFMEMORY;
1614
1615     szwName = strdupAtoW( szName );
1616     if( szName && !szwName )
1617         goto end;
1618
1619     szwValue = strdupAtoW( szValue );
1620     if( szValue && !szwValue )
1621         goto end;
1622
1623     r = MsiSetPropertyW( hInstall, szwName, szwValue);
1624
1625 end:
1626     msi_free( szwName );
1627     msi_free( szwValue );
1628
1629     return r;
1630 }
1631
1632 void msi_reset_folders( MSIPACKAGE *package, BOOL source )
1633 {
1634     MSIFOLDER *folder;
1635
1636     LIST_FOR_EACH_ENTRY( folder, &package->folders, MSIFOLDER, entry )
1637     {
1638         if ( source )
1639         {
1640             msi_free( folder->ResolvedSource );
1641             folder->ResolvedSource = NULL;
1642         }
1643         else
1644         {
1645             msi_free( folder->ResolvedTarget );
1646             folder->ResolvedTarget = NULL;
1647         }
1648     }
1649 }
1650
1651 UINT msi_set_property( MSIDATABASE *db, LPCWSTR szName, LPCWSTR szValue )
1652 {
1653     MSIQUERY *view;
1654     MSIRECORD *row = NULL;
1655     UINT rc;
1656     DWORD sz = 0;
1657     WCHAR Query[1024];
1658
1659     static const WCHAR Insert[] = {
1660         'I','N','S','E','R','T',' ','i','n','t','o',' ',
1661         '`','_','P','r','o','p','e','r','t','y','`',' ','(',
1662         '`','_','P','r','o','p','e','r','t','y','`',',',
1663         '`','V','a','l','u','e','`',')',' ','V','A','L','U','E','S'
1664         ,' ','(','?',',','?',')',0};
1665     static const WCHAR Update[] = {
1666         'U','P','D','A','T','E',' ','`','_','P','r','o','p','e','r','t','y','`',
1667         ' ','s','e','t',' ','`','V','a','l','u','e','`',' ','=',' ','?',' ',
1668         'w','h','e','r','e',' ','`','_','P','r','o','p','e','r','t','y','`',
1669         ' ','=',' ','\'','%','s','\'',0};
1670     static const WCHAR Delete[] = {
1671         'D','E','L','E','T','E',' ','F','R','O','M',' ',
1672         '`','_','P','r','o','p','e','r','t','y','`',' ','W','H','E','R','E',' ',
1673         '`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0};
1674
1675     TRACE("%p %s %s\n", db, debugstr_w(szName), debugstr_w(szValue));
1676
1677     if (!szName)
1678         return ERROR_INVALID_PARAMETER;
1679
1680     /* this one is weird... */
1681     if (!szName[0])
1682         return szValue ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS;
1683
1684     rc = msi_get_property(db, szName, 0, &sz);
1685     if (!szValue || !*szValue)
1686     {
1687         sprintfW(Query, Delete, szName);
1688     }
1689     else if (rc == ERROR_MORE_DATA || rc == ERROR_SUCCESS)
1690     {
1691         sprintfW(Query, Update, szName);
1692
1693         row = MSI_CreateRecord(1);
1694         MSI_RecordSetStringW(row, 1, szValue);
1695     }
1696     else
1697     {
1698         strcpyW(Query, Insert);
1699
1700         row = MSI_CreateRecord(2);
1701         MSI_RecordSetStringW(row, 1, szName);
1702         MSI_RecordSetStringW(row, 2, szValue);
1703     }
1704
1705     rc = MSI_DatabaseOpenViewW(db, Query, &view);
1706     if (rc == ERROR_SUCCESS)
1707     {
1708         rc = MSI_ViewExecute(view, row);
1709         MSI_ViewClose(view);
1710         msiobj_release(&view->hdr);
1711     }
1712
1713     if (row)
1714       msiobj_release(&row->hdr);
1715
1716     return rc;
1717 }
1718
1719 UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue)
1720 {
1721     MSIPACKAGE *package;
1722     UINT ret;
1723
1724     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
1725     if( !package )
1726     {
1727         HRESULT hr;
1728         BSTR name = NULL, value = NULL;
1729         IWineMsiRemotePackage *remote_package;
1730
1731         remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
1732         if (!remote_package)
1733             return ERROR_INVALID_HANDLE;
1734
1735         name = SysAllocString( szName );
1736         value = SysAllocString( szValue );
1737         if ((!name && szName) || (!value && szValue))
1738         {
1739             SysFreeString( name );
1740             SysFreeString( value );
1741             IWineMsiRemotePackage_Release( remote_package );
1742             return ERROR_OUTOFMEMORY;
1743         }
1744
1745         hr = IWineMsiRemotePackage_SetProperty( remote_package, name, value );
1746
1747         SysFreeString( name );
1748         SysFreeString( value );
1749         IWineMsiRemotePackage_Release( remote_package );
1750
1751         if (FAILED(hr))
1752         {
1753             if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1754                 return HRESULT_CODE(hr);
1755
1756             return ERROR_FUNCTION_FAILED;
1757         }
1758
1759         return ERROR_SUCCESS;
1760     }
1761
1762     ret = msi_set_property( package->db, szName, szValue );
1763     if (ret == ERROR_SUCCESS && !strcmpW( szName, cszSourceDir ))
1764         msi_reset_folders( package, TRUE );
1765
1766     msiobj_release( &package->hdr );
1767     return ret;
1768 }
1769
1770 static MSIRECORD *msi_get_property_row( MSIDATABASE *db, LPCWSTR name )
1771 {
1772     MSIQUERY *view;
1773     MSIRECORD *rec, *row = NULL;
1774     UINT r;
1775
1776     static const WCHAR query[]= {
1777         'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ',
1778         'F','R','O','M',' ' ,'`','_','P','r','o','p','e','r','t','y','`',
1779         ' ','W','H','E','R','E',' ' ,'`','_','P','r','o','p','e','r','t','y','`',
1780         '=','?',0};
1781
1782     if (!name || !*name)
1783         return NULL;
1784
1785     rec = MSI_CreateRecord(1);
1786     if (!rec)
1787         return NULL;
1788
1789     MSI_RecordSetStringW(rec, 1, name);
1790
1791     r = MSI_DatabaseOpenViewW(db, query, &view);
1792     if (r == ERROR_SUCCESS)
1793     {
1794         MSI_ViewExecute(view, rec);
1795         MSI_ViewFetch(view, &row);
1796         MSI_ViewClose(view);
1797         msiobj_release(&view->hdr);
1798     }
1799
1800     msiobj_release(&rec->hdr);
1801     return row;
1802 }
1803
1804 /* internal function, not compatible with MsiGetPropertyW */
1805 UINT msi_get_property( MSIDATABASE *db, LPCWSTR szName,
1806                        LPWSTR szValueBuf, LPDWORD pchValueBuf )
1807 {
1808     MSIRECORD *row;
1809     UINT rc = ERROR_FUNCTION_FAILED;
1810
1811     row = msi_get_property_row( db, szName );
1812
1813     if (*pchValueBuf > 0)
1814         szValueBuf[0] = 0;
1815
1816     if (row)
1817     {
1818         rc = MSI_RecordGetStringW(row, 1, szValueBuf, pchValueBuf);
1819         msiobj_release(&row->hdr);
1820     }
1821
1822     if (rc == ERROR_SUCCESS)
1823         TRACE("returning %s for property %s\n", debugstr_w(szValueBuf),
1824             debugstr_w(szName));
1825     else if (rc == ERROR_MORE_DATA)
1826         TRACE("need %d sized buffer for %s\n", *pchValueBuf,
1827             debugstr_w(szName));
1828     else
1829     {
1830         *pchValueBuf = 0;
1831         TRACE("property %s not found\n", debugstr_w(szName));
1832     }
1833
1834     return rc;
1835 }
1836
1837 LPWSTR msi_dup_property(MSIDATABASE *db, LPCWSTR prop)
1838 {
1839     DWORD sz = 0;
1840     LPWSTR str;
1841     UINT r;
1842
1843     r = msi_get_property(db, prop, NULL, &sz);
1844     if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
1845         return NULL;
1846
1847     sz++;
1848     str = msi_alloc(sz * sizeof(WCHAR));
1849     r = msi_get_property(db, prop, str, &sz);
1850     if (r != ERROR_SUCCESS)
1851     {
1852         msi_free(str);
1853         str = NULL;
1854     }
1855
1856     return str;
1857 }
1858
1859 int msi_get_property_int( MSIDATABASE *db, LPCWSTR prop, int def )
1860 {
1861     LPWSTR str = msi_dup_property( db, prop );
1862     int val = str ? atoiW(str) : def;
1863     msi_free(str);
1864     return val;
1865 }
1866
1867 static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name,
1868                              awstring *szValueBuf, LPDWORD pchValueBuf )
1869 {
1870     MSIPACKAGE *package;
1871     MSIRECORD *row = NULL;
1872     UINT r = ERROR_FUNCTION_FAILED;
1873     LPCWSTR val = NULL;
1874
1875     TRACE("%u %s %p %p\n", handle, debugstr_w(name),
1876           szValueBuf->str.w, pchValueBuf );
1877
1878     if (!name)
1879         return ERROR_INVALID_PARAMETER;
1880
1881     package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE );
1882     if (!package)
1883     {
1884         HRESULT hr;
1885         IWineMsiRemotePackage *remote_package;
1886         LPWSTR value = NULL;
1887         BSTR bname;
1888         DWORD len;
1889
1890         remote_package = (IWineMsiRemotePackage *)msi_get_remote( handle );
1891         if (!remote_package)
1892             return ERROR_INVALID_HANDLE;
1893
1894         bname = SysAllocString( name );
1895         if (!bname)
1896         {
1897             IWineMsiRemotePackage_Release( remote_package );
1898             return ERROR_OUTOFMEMORY;
1899         }
1900
1901         len = 0;
1902         hr = IWineMsiRemotePackage_GetProperty( remote_package, bname, NULL, &len );
1903         if (FAILED(hr))
1904             goto done;
1905
1906         len++;
1907         value = msi_alloc(len * sizeof(WCHAR));
1908         if (!value)
1909         {
1910             r = ERROR_OUTOFMEMORY;
1911             goto done;
1912         }
1913
1914         hr = IWineMsiRemotePackage_GetProperty( remote_package, bname, (BSTR *)value, &len );
1915         if (FAILED(hr))
1916             goto done;
1917
1918         r = msi_strcpy_to_awstring( value, szValueBuf, pchValueBuf );
1919
1920         /* Bug required by Adobe installers */
1921         if (!szValueBuf->unicode && !szValueBuf->str.a)
1922             *pchValueBuf *= sizeof(WCHAR);
1923
1924 done:
1925         IWineMsiRemotePackage_Release(remote_package);
1926         SysFreeString(bname);
1927         msi_free(value);
1928
1929         if (FAILED(hr))
1930         {
1931             if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1932                 return HRESULT_CODE(hr);
1933
1934             return ERROR_FUNCTION_FAILED;
1935         }
1936
1937         return r;
1938     }
1939
1940     row = msi_get_property_row( package->db, name );
1941     if (row)
1942         val = MSI_RecordGetString( row, 1 );
1943
1944     if (!val)
1945         val = szEmpty;
1946
1947     r = msi_strcpy_to_awstring( val, szValueBuf, pchValueBuf );
1948
1949     if (row)
1950         msiobj_release( &row->hdr );
1951     msiobj_release( &package->hdr );
1952
1953     return r;
1954 }
1955
1956 UINT WINAPI MsiGetPropertyA( MSIHANDLE hInstall, LPCSTR szName,
1957                              LPSTR szValueBuf, LPDWORD pchValueBuf )
1958 {
1959     awstring val;
1960     LPWSTR name;
1961     UINT r;
1962
1963     val.unicode = FALSE;
1964     val.str.a = szValueBuf;
1965
1966     name = strdupAtoW( szName );
1967     if (szName && !name)
1968         return ERROR_OUTOFMEMORY;
1969
1970     r = MSI_GetProperty( hInstall, name, &val, pchValueBuf );
1971     msi_free( name );
1972     return r;
1973 }
1974
1975 UINT WINAPI MsiGetPropertyW( MSIHANDLE hInstall, LPCWSTR szName,
1976                              LPWSTR szValueBuf, LPDWORD pchValueBuf )
1977 {
1978     awstring val;
1979
1980     val.unicode = TRUE;
1981     val.str.w = szValueBuf;
1982
1983     return MSI_GetProperty( hInstall, szName, &val, pchValueBuf );
1984 }
1985
1986 typedef struct _msi_remote_package_impl {
1987     const IWineMsiRemotePackageVtbl *lpVtbl;
1988     MSIHANDLE package;
1989     LONG refs;
1990 } msi_remote_package_impl;
1991
1992 static inline msi_remote_package_impl* mrp_from_IWineMsiRemotePackage( IWineMsiRemotePackage* iface )
1993 {
1994     return (msi_remote_package_impl*) iface;
1995 }
1996
1997 static HRESULT WINAPI mrp_QueryInterface( IWineMsiRemotePackage *iface,
1998                 REFIID riid,LPVOID *ppobj)
1999 {
2000     if( IsEqualCLSID( riid, &IID_IUnknown ) ||
2001         IsEqualCLSID( riid, &IID_IWineMsiRemotePackage ) )
2002     {
2003         IUnknown_AddRef( iface );
2004         *ppobj = iface;
2005         return S_OK;
2006     }
2007
2008     return E_NOINTERFACE;
2009 }
2010
2011 static ULONG WINAPI mrp_AddRef( IWineMsiRemotePackage *iface )
2012 {
2013     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2014
2015     return InterlockedIncrement( &This->refs );
2016 }
2017
2018 static ULONG WINAPI mrp_Release( IWineMsiRemotePackage *iface )
2019 {
2020     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2021     ULONG r;
2022
2023     r = InterlockedDecrement( &This->refs );
2024     if (r == 0)
2025     {
2026         MsiCloseHandle( This->package );
2027         msi_free( This );
2028     }
2029     return r;
2030 }
2031
2032 static HRESULT WINAPI mrp_SetMsiHandle( IWineMsiRemotePackage *iface, MSIHANDLE handle )
2033 {
2034     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2035     This->package = handle;
2036     return S_OK;
2037 }
2038
2039 static HRESULT WINAPI mrp_GetActiveDatabase( IWineMsiRemotePackage *iface, MSIHANDLE *handle )
2040 {
2041     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2042     IWineMsiRemoteDatabase *rdb = NULL;
2043     HRESULT hr;
2044     MSIHANDLE hdb;
2045
2046     hr = create_msi_remote_database( NULL, (LPVOID *)&rdb );
2047     if (FAILED(hr) || !rdb)
2048     {
2049         ERR("Failed to create remote database\n");
2050         return hr;
2051     }
2052
2053     hdb = MsiGetActiveDatabase(This->package);
2054
2055     hr = IWineMsiRemoteDatabase_SetMsiHandle( rdb, hdb );
2056     if (FAILED(hr))
2057     {
2058         ERR("Failed to set the database handle\n");
2059         return hr;
2060     }
2061
2062     *handle = alloc_msi_remote_handle( (IUnknown *)rdb );
2063     return S_OK;
2064 }
2065
2066 static HRESULT WINAPI mrp_GetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR *value, DWORD *size )
2067 {
2068     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2069     UINT r;
2070
2071     r = MsiGetPropertyW(This->package, (LPWSTR)property, (LPWSTR)value, size);
2072     if (r != ERROR_SUCCESS)
2073         return HRESULT_FROM_WIN32(r);
2074
2075     return S_OK;
2076 }
2077
2078 static HRESULT WINAPI mrp_SetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR value )
2079 {
2080     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2081     UINT r = MsiSetPropertyW(This->package, property, value);
2082     return HRESULT_FROM_WIN32(r);
2083 }
2084
2085 static HRESULT WINAPI mrp_ProcessMessage( IWineMsiRemotePackage *iface, INSTALLMESSAGE message, MSIHANDLE record )
2086 {
2087     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2088     UINT r = MsiProcessMessage(This->package, message, record);
2089     return HRESULT_FROM_WIN32(r);
2090 }
2091
2092 static HRESULT WINAPI mrp_DoAction( IWineMsiRemotePackage *iface, BSTR action )
2093 {
2094     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2095     UINT r = MsiDoActionW(This->package, action);
2096     return HRESULT_FROM_WIN32(r);
2097 }
2098
2099 static HRESULT WINAPI mrp_Sequence( IWineMsiRemotePackage *iface, BSTR table, int sequence )
2100 {
2101     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2102     UINT r = MsiSequenceW(This->package, table, sequence);
2103     return HRESULT_FROM_WIN32(r);
2104 }
2105
2106 static HRESULT WINAPI mrp_GetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR *value, DWORD *size )
2107 {
2108     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2109     UINT r = MsiGetTargetPathW(This->package, (LPWSTR)folder, (LPWSTR)value, size);
2110     return HRESULT_FROM_WIN32(r);
2111 }
2112
2113 static HRESULT WINAPI mrp_SetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR value)
2114 {
2115     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2116     UINT r = MsiSetTargetPathW(This->package, folder, value);
2117     return HRESULT_FROM_WIN32(r);
2118 }
2119
2120 static HRESULT WINAPI mrp_GetSourcePath( IWineMsiRemotePackage *iface, BSTR folder, BSTR *value, DWORD *size )
2121 {
2122     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2123     UINT r = MsiGetSourcePathW(This->package, (LPWSTR)folder, (LPWSTR)value, size);
2124     return HRESULT_FROM_WIN32(r);
2125 }
2126
2127 static HRESULT WINAPI mrp_GetMode( IWineMsiRemotePackage *iface, MSIRUNMODE mode, BOOL *ret )
2128 {
2129     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2130     *ret = MsiGetMode(This->package, mode);
2131     return S_OK;
2132 }
2133
2134 static HRESULT WINAPI mrp_SetMode( IWineMsiRemotePackage *iface, MSIRUNMODE mode, BOOL state )
2135 {
2136     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2137     UINT r = MsiSetMode(This->package, mode, state);
2138     return HRESULT_FROM_WIN32(r);
2139 }
2140
2141 static HRESULT WINAPI mrp_GetFeatureState( IWineMsiRemotePackage *iface, BSTR feature,
2142                                     INSTALLSTATE *installed, INSTALLSTATE *action )
2143 {
2144     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2145     UINT r = MsiGetFeatureStateW(This->package, feature, installed, action);
2146     return HRESULT_FROM_WIN32(r);
2147 }
2148
2149 static HRESULT WINAPI mrp_SetFeatureState( IWineMsiRemotePackage *iface, BSTR feature, INSTALLSTATE state )
2150 {
2151     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2152     UINT r = MsiSetFeatureStateW(This->package, feature, state);
2153     return HRESULT_FROM_WIN32(r);
2154 }
2155
2156 static HRESULT WINAPI mrp_GetComponentState( IWineMsiRemotePackage *iface, BSTR component,
2157                                       INSTALLSTATE *installed, INSTALLSTATE *action )
2158 {
2159     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2160     UINT r = MsiGetComponentStateW(This->package, component, installed, action);
2161     return HRESULT_FROM_WIN32(r);
2162 }
2163
2164 static HRESULT WINAPI mrp_SetComponentState( IWineMsiRemotePackage *iface, BSTR component, INSTALLSTATE state )
2165 {
2166     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2167     UINT r = MsiSetComponentStateW(This->package, component, state);
2168     return HRESULT_FROM_WIN32(r);
2169 }
2170
2171 static HRESULT WINAPI mrp_GetLanguage( IWineMsiRemotePackage *iface, LANGID *language )
2172 {
2173     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2174     *language = MsiGetLanguage(This->package);
2175     return S_OK;
2176 }
2177
2178 static HRESULT WINAPI mrp_SetInstallLevel( IWineMsiRemotePackage *iface, int level )
2179 {
2180     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2181     UINT r = MsiSetInstallLevel(This->package, level);
2182     return HRESULT_FROM_WIN32(r);
2183 }
2184
2185 static HRESULT WINAPI mrp_FormatRecord( IWineMsiRemotePackage *iface, MSIHANDLE record,
2186                                         BSTR *value)
2187 {
2188     DWORD size = 0;
2189     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2190     UINT r = MsiFormatRecordW(This->package, record, NULL, &size);
2191     if (r == ERROR_SUCCESS)
2192     {
2193         *value = SysAllocStringLen(NULL, size);
2194         if (!*value)
2195             return E_OUTOFMEMORY;
2196         size++;
2197         r = MsiFormatRecordW(This->package, record, *value, &size);
2198     }
2199     return HRESULT_FROM_WIN32(r);
2200 }
2201
2202 static HRESULT WINAPI mrp_EvaluateCondition( IWineMsiRemotePackage *iface, BSTR condition )
2203 {
2204     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2205     UINT r = MsiEvaluateConditionW(This->package, condition);
2206     return HRESULT_FROM_WIN32(r);
2207 }
2208
2209 static HRESULT WINAPI mrp_GetFeatureCost( IWineMsiRemotePackage *iface, BSTR feature,
2210                                           INT cost_tree, INSTALLSTATE state, INT *cost )
2211 {
2212     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2213     UINT r = MsiGetFeatureCostW(This->package, feature, cost_tree, state, cost);
2214     return HRESULT_FROM_WIN32(r);
2215 }
2216
2217 static const IWineMsiRemotePackageVtbl msi_remote_package_vtbl =
2218 {
2219     mrp_QueryInterface,
2220     mrp_AddRef,
2221     mrp_Release,
2222     mrp_SetMsiHandle,
2223     mrp_GetActiveDatabase,
2224     mrp_GetProperty,
2225     mrp_SetProperty,
2226     mrp_ProcessMessage,
2227     mrp_DoAction,
2228     mrp_Sequence,
2229     mrp_GetTargetPath,
2230     mrp_SetTargetPath,
2231     mrp_GetSourcePath,
2232     mrp_GetMode,
2233     mrp_SetMode,
2234     mrp_GetFeatureState,
2235     mrp_SetFeatureState,
2236     mrp_GetComponentState,
2237     mrp_SetComponentState,
2238     mrp_GetLanguage,
2239     mrp_SetInstallLevel,
2240     mrp_FormatRecord,
2241     mrp_EvaluateCondition,
2242     mrp_GetFeatureCost,
2243 };
2244
2245 HRESULT create_msi_remote_package( IUnknown *pOuter, LPVOID *ppObj )
2246 {
2247     msi_remote_package_impl* This;
2248
2249     This = msi_alloc( sizeof *This );
2250     if (!This)
2251         return E_OUTOFMEMORY;
2252
2253     This->lpVtbl = &msi_remote_package_vtbl;
2254     This->package = 0;
2255     This->refs = 1;
2256
2257     *ppObj = This;
2258
2259     return S_OK;
2260 }
2261
2262 UINT msi_package_add_info(MSIPACKAGE *package, DWORD context, DWORD options,
2263                           LPCWSTR property, LPWSTR value)
2264 {
2265     MSISOURCELISTINFO *info;
2266
2267     info = msi_alloc(sizeof(MSISOURCELISTINFO));
2268     if (!info)
2269         return ERROR_OUTOFMEMORY;
2270
2271     info->context = context;
2272     info->options = options;
2273     info->property = property;
2274     info->value = strdupW(value);
2275     list_add_head(&package->sourcelist_info, &info->entry);
2276
2277     return ERROR_SUCCESS;
2278 }
2279
2280 UINT msi_package_add_media_disk(MSIPACKAGE *package, DWORD context, DWORD options,
2281                                 DWORD disk_id, LPWSTR volume_label, LPWSTR disk_prompt)
2282 {
2283     MSIMEDIADISK *disk;
2284
2285     disk = msi_alloc(sizeof(MSIMEDIADISK));
2286     if (!disk)
2287         return ERROR_OUTOFMEMORY;
2288
2289     disk->context = context;
2290     disk->options = options;
2291     disk->disk_id = disk_id;
2292     disk->volume_label = strdupW(volume_label);
2293     disk->disk_prompt = strdupW(disk_prompt);
2294     list_add_head(&package->sourcelist_media, &disk->entry);
2295
2296     return ERROR_SUCCESS;
2297 }