kernel32: Remove superfluous heap reallocation calls in FormatMessageA/W.
[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_SetPropertyW( package, 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_SetPropertyW( package, 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_SetPropertyW(package, 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_SetPropertyW(package, CFF, pth);
693
694     SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES,NULL,0,pth);
695     strcatW(pth, szBackSlash);
696     MSI_SetPropertyW(package, PFF, pth);
697
698     SHGetFolderPathW(NULL,CSIDL_COMMON_APPDATA,NULL,0,pth);
699     strcatW(pth, szBackSlash);
700     MSI_SetPropertyW(package, CADF, pth);
701
702     SHGetFolderPathW(NULL,CSIDL_FAVORITES,NULL,0,pth);
703     strcatW(pth, szBackSlash);
704     MSI_SetPropertyW(package, FaF, pth);
705
706     SHGetFolderPathW(NULL,CSIDL_FONTS,NULL,0,pth);
707     strcatW(pth, szBackSlash);
708     MSI_SetPropertyW(package, FoF, pth);
709
710     SHGetFolderPathW(NULL,CSIDL_SENDTO,NULL,0,pth);
711     strcatW(pth, szBackSlash);
712     MSI_SetPropertyW(package, SendTF, pth);
713
714     SHGetFolderPathW(NULL,CSIDL_STARTMENU,NULL,0,pth);
715     strcatW(pth, szBackSlash);
716     MSI_SetPropertyW(package, SMF, pth);
717
718     SHGetFolderPathW(NULL,CSIDL_STARTUP,NULL,0,pth);
719     strcatW(pth, szBackSlash);
720     MSI_SetPropertyW(package, StF, pth);
721
722     SHGetFolderPathW(NULL,CSIDL_TEMPLATES,NULL,0,pth);
723     strcatW(pth, szBackSlash);
724     MSI_SetPropertyW(package, TemplF, pth);
725
726     SHGetFolderPathW(NULL,CSIDL_DESKTOP,NULL,0,pth);
727     strcatW(pth, szBackSlash);
728     MSI_SetPropertyW(package, DF, pth);
729
730     SHGetFolderPathW(NULL,CSIDL_PROGRAMS,NULL,0,pth);
731     strcatW(pth, szBackSlash);
732     MSI_SetPropertyW(package, PMF, pth);
733
734     SHGetFolderPathW(NULL,CSIDL_ADMINTOOLS,NULL,0,pth);
735     strcatW(pth, szBackSlash);
736     MSI_SetPropertyW(package, ATF, pth);
737
738     SHGetFolderPathW(NULL,CSIDL_APPDATA,NULL,0,pth);
739     strcatW(pth, szBackSlash);
740     MSI_SetPropertyW(package, ADF, pth);
741
742     SHGetFolderPathW(NULL,CSIDL_SYSTEM,NULL,0,pth);
743     strcatW(pth, szBackSlash);
744     MSI_SetPropertyW(package, SF, pth);
745     MSI_SetPropertyW(package, SF16, pth);
746
747     SHGetFolderPathW(NULL,CSIDL_LOCAL_APPDATA,NULL,0,pth);
748     strcatW(pth, szBackSlash);
749     MSI_SetPropertyW(package, LADF, pth);
750
751     SHGetFolderPathW(NULL,CSIDL_MYPICTURES,NULL,0,pth);
752     strcatW(pth, szBackSlash);
753     MSI_SetPropertyW(package, MPF, pth);
754
755     SHGetFolderPathW(NULL,CSIDL_PERSONAL,NULL,0,pth);
756     strcatW(pth, szBackSlash);
757     MSI_SetPropertyW(package, PF, pth);
758
759     SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
760     strcatW(pth, szBackSlash);
761     MSI_SetPropertyW(package, 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_SetPropertyW(package, szPhysicalMemory, bufstr);
768
769     SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
770     ptr = strchrW(pth,'\\');
771     if (ptr)
772         *(ptr+1) = 0;
773     MSI_SetPropertyW(package, WV, pth);
774     
775     GetTempPathW(MAX_PATH,pth);
776     MSI_SetPropertyW(package, TF, pth);
777
778
779     /* in a wine environment the user is always admin and privileged */
780     MSI_SetPropertyW(package,szAdminUser,szOne);
781     MSI_SetPropertyW(package,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_SetPropertyW(package,v9x,verstr);
792             break;
793         case VER_PLATFORM_WIN32_NT:
794             MSI_SetPropertyW(package,vNT,verstr);
795             sprintfW(verstr,szFormat,OSVersion.wProductType);
796             MSI_SetPropertyW(package,szMsiNTProductType,verstr);
797             break;
798     }
799     sprintfW(verstr,szFormat,OSVersion.dwBuildNumber);
800     MSI_SetPropertyW(package,szWinBuild,verstr);
801     /* just fudge this */
802     MSI_SetPropertyW(package,szSPL,szSix);
803
804     sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION);
805     MSI_SetPropertyW( package, szVersionMsi, bufstr );
806     sprintfW( bufstr, szFormat, MSI_MAJORVERSION * 100);
807     MSI_SetPropertyW( package, 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_SetPropertyW( package, szIntel, bufstr );
814     }
815
816     /* Screen properties. */
817     dc = GetDC(0);
818     sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, HORZRES ) );
819     MSI_SetPropertyW( package, szScreenX, bufstr );
820     sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, VERTRES ));
821     MSI_SetPropertyW( package, szScreenY, bufstr );
822     sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, BITSPIXEL ));
823     MSI_SetPropertyW( package, szColorBits, bufstr );
824     ReleaseDC(0, dc);
825
826     /* USERNAME and COMPANYNAME */
827     username = msi_dup_property( package, szUSERNAME );
828     companyname = msi_dup_property( package, 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_SetPropertyW( package, szUSERNAME, username );
836         if (!companyname &&
837             (companyname = msi_reg_get_val_str( hkey, szDefCompany )))
838             MSI_SetPropertyW( package, 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_SetPropertyW( package, szUSERNAME, username );
847         if (!companyname &&
848             (companyname = msi_reg_get_val_str( hkey, szRegisteredOrg )))
849             MSI_SetPropertyW( package, 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_SetPropertyW( package, 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_SetPropertyW( package, 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
879     MSI_SetPropertyW( package, szUserLangID, bufstr );
880
881     langid = GetSystemDefaultLangID();
882     sprintfW(bufstr, szIntFormat, langid);
883
884     MSI_SetPropertyW( package, szSystemLangID, bufstr );
885
886     sprintfW(bufstr, szIntFormat, MsiQueryProductStateW(package->ProductCode));
887     MSI_SetPropertyW( package, szProductState, bufstr );
888
889     len = 0;
890     if (!GetUserNameW( NULL, &len ) && GetLastError() == ERROR_MORE_DATA)
891     {
892         WCHAR *username;
893         if ((username = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
894         {
895             if (GetUserNameW( username, &len ))
896                 MSI_SetPropertyW( package, szLogonUser, username );
897             HeapFree( GetProcessHeap(), 0, username );
898         }
899     }
900 }
901
902 static UINT msi_load_summary_properties( MSIPACKAGE *package )
903 {
904     UINT rc;
905     MSIHANDLE suminfo;
906     MSIHANDLE hdb = alloc_msihandle( &package->db->hdr );
907     INT count;
908     DWORD len;
909     LPWSTR package_code;
910     static const WCHAR szPackageCode[] = {
911         'P','a','c','k','a','g','e','C','o','d','e',0};
912
913     if (!hdb) {
914         ERR("Unable to allocate handle\n");
915         return ERROR_OUTOFMEMORY;
916     }
917
918     rc = MsiGetSummaryInformationW( hdb, NULL, 0, &suminfo );
919     MsiCloseHandle(hdb);
920     if (rc != ERROR_SUCCESS)
921     {
922         ERR("Unable to open Summary Information\n");
923         return rc;
924     }
925
926     rc = MsiSummaryInfoGetPropertyW( suminfo, PID_PAGECOUNT, NULL,
927                                      &count, NULL, NULL, NULL );
928     if (rc != ERROR_SUCCESS)
929     {
930         WARN("Unable to query page count: %d\n", rc);
931         goto done;
932     }
933
934     /* load package code property */
935     len = 0;
936     rc = MsiSummaryInfoGetPropertyW( suminfo, PID_REVNUMBER, NULL,
937                                      NULL, NULL, NULL, &len );
938     if (rc != ERROR_MORE_DATA)
939     {
940         WARN("Unable to query revision number: %d\n", rc);
941         rc = ERROR_FUNCTION_FAILED;
942         goto done;
943     }
944
945     len++;
946     package_code = msi_alloc( len * sizeof(WCHAR) );
947     rc = MsiSummaryInfoGetPropertyW( suminfo, PID_REVNUMBER, NULL,
948                                      NULL, NULL, package_code, &len );
949     if (rc != ERROR_SUCCESS)
950     {
951         WARN("Unable to query rev number: %d\n", rc);
952         goto done;
953     }
954
955     MSI_SetPropertyW( package, szPackageCode, package_code );
956     msi_free( package_code );
957
958     /* load package attributes */
959     count = 0;
960     MsiSummaryInfoGetPropertyW( suminfo, PID_WORDCOUNT, NULL,
961                                 &count, NULL, NULL, NULL );
962     package->WordCount = count;
963
964 done:
965     MsiCloseHandle(suminfo);
966     return rc;
967 }
968
969 static MSIPACKAGE *msi_alloc_package( void )
970 {
971     MSIPACKAGE *package;
972
973     package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE),
974                                MSI_FreePackage );
975     if( package )
976     {
977         list_init( &package->components );
978         list_init( &package->features );
979         list_init( &package->files );
980         list_init( &package->tempfiles );
981         list_init( &package->folders );
982         list_init( &package->subscriptions );
983         list_init( &package->appids );
984         list_init( &package->classes );
985         list_init( &package->mimes );
986         list_init( &package->extensions );
987         list_init( &package->progids );
988         list_init( &package->RunningActions );
989         list_init( &package->sourcelist_info );
990         list_init( &package->sourcelist_media );
991     }
992
993     return package;
994 }
995
996 static UINT msi_load_admin_properties(MSIPACKAGE *package)
997 {
998     BYTE *data;
999     UINT r, sz;
1000
1001     static const WCHAR stmname[] = {'A','d','m','i','n','P','r','o','p','e','r','t','i','e','s',0};
1002
1003     r = read_stream_data(package->db->storage, stmname, FALSE, &data, &sz);
1004     if (r != ERROR_SUCCESS)
1005         return r;
1006
1007     r = msi_parse_command_line(package, (WCHAR *)data, TRUE);
1008
1009     msi_free(data);
1010     return r;
1011 }
1012
1013 static void adjust_allusers_property( MSIPACKAGE *package )
1014 {
1015     /* FIXME: this should depend on the user's privileges */
1016     if (msi_get_property_int( package, szAllUsers, 0 ) == 2)
1017     {
1018         TRACE("resetting ALLUSERS property from 2 to 1\n");
1019         MSI_SetPropertyW( package, szAllUsers, szOne );
1020     }
1021 }
1022
1023 MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url )
1024 {
1025     static const WCHAR szLevel[] = { 'U','I','L','e','v','e','l',0 };
1026     static const WCHAR szpi[] = {'%','i',0};
1027     MSIPACKAGE *package;
1028     WCHAR uilevel[10];
1029     UINT r;
1030
1031     TRACE("%p\n", db);
1032
1033     package = msi_alloc_package();
1034     if (package)
1035     {
1036         msiobj_addref( &db->hdr );
1037         package->db = db;
1038
1039         package->WordCount = 0;
1040         package->PackagePath = strdupW( db->path );
1041         package->BaseURL = strdupW( base_url );
1042
1043         create_temp_property_table( package );
1044         msi_clone_properties( package );
1045
1046         package->ProductCode = msi_dup_property( package, szProductCode );
1047         set_installed_prop( package );
1048         set_installer_properties( package );
1049
1050         sprintfW(uilevel,szpi,gUILevel);
1051         MSI_SetPropertyW(package, szLevel, uilevel);
1052
1053         r = msi_load_summary_properties( package );
1054         if (r != ERROR_SUCCESS)
1055         {
1056             msiobj_release( &package->hdr );
1057             return NULL;
1058         }
1059
1060         if (package->WordCount & msidbSumInfoSourceTypeAdminImage)
1061             msi_load_admin_properties( package );
1062
1063         adjust_allusers_property( package );
1064     }
1065
1066     return package;
1067 }
1068
1069 /*
1070  * copy_package_to_temp   [internal]
1071  *
1072  * copy the msi file to a temp file to prevent locking a CD
1073  * with a multi disc install 
1074  *
1075  * FIXME: I think this is wrong, and instead of copying the package,
1076  *        we should read all the tables to memory, then open the
1077  *        database to read binary streams on demand.
1078  */ 
1079 static UINT copy_package_to_temp( LPCWSTR szPackage, LPWSTR filename )
1080 {
1081     WCHAR path[MAX_PATH];
1082
1083     GetTempPathW( MAX_PATH, path );
1084     GetTempFileNameW( path, szMsi, 0, filename );
1085
1086     if( !CopyFileW( szPackage, filename, FALSE ) )
1087     {
1088         UINT error = GetLastError();
1089         ERR("failed to copy package %s to %s (%u)\n", debugstr_w(szPackage), debugstr_w(filename), error);
1090         DeleteFileW( filename );
1091         return error;
1092     }
1093
1094     return ERROR_SUCCESS;
1095 }
1096
1097 UINT msi_download_file( LPCWSTR szUrl, LPWSTR filename )
1098 {
1099     LPINTERNET_CACHE_ENTRY_INFOW cache_entry;
1100     DWORD size = 0;
1101     HRESULT hr;
1102
1103     /* call will always fail, becase size is 0,
1104      * but will return ERROR_FILE_NOT_FOUND first
1105      * if the file doesn't exist
1106      */
1107     GetUrlCacheEntryInfoW( szUrl, NULL, &size );
1108     if ( GetLastError() != ERROR_FILE_NOT_FOUND )
1109     {
1110         cache_entry = HeapAlloc( GetProcessHeap(), 0, size );
1111         if ( !GetUrlCacheEntryInfoW( szUrl, cache_entry, &size ) )
1112         {
1113             UINT error = GetLastError();
1114             HeapFree( GetProcessHeap(), 0, cache_entry );
1115             return error;
1116         }
1117
1118         lstrcpyW( filename, cache_entry->lpszLocalFileName );
1119         HeapFree( GetProcessHeap(), 0, cache_entry );
1120         return ERROR_SUCCESS;
1121     }
1122
1123     hr = URLDownloadToCacheFileW( NULL, szUrl, filename, MAX_PATH, 0, NULL );
1124     if ( FAILED(hr) )
1125     {
1126         WARN("failed to download %s to cache file\n", debugstr_w(szUrl));
1127         return ERROR_FUNCTION_FAILED;
1128     }
1129
1130     return ERROR_SUCCESS;
1131 }
1132
1133 static UINT msi_get_local_package_name( LPWSTR path )
1134 {
1135     static const WCHAR szInstaller[] = {
1136         '\\','I','n','s','t','a','l','l','e','r','\\',0};
1137     static const WCHAR fmt[] = { '%','x','.','m','s','i',0};
1138     DWORD time, len, i;
1139     HANDLE handle;
1140
1141     time = GetTickCount();
1142     GetWindowsDirectoryW( path, MAX_PATH );
1143     strcatW( path, szInstaller );
1144     CreateDirectoryW( path, NULL );
1145
1146     len = strlenW(path);
1147     for (i = 0; i < 0x10000; i++)
1148     {
1149         snprintfW( &path[len], MAX_PATH - len, fmt, (time + i)&0xffff );
1150         handle = CreateFileW( path, GENERIC_WRITE, 0, NULL,
1151                               CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
1152         if (handle != INVALID_HANDLE_VALUE)
1153         {
1154             CloseHandle(handle);
1155             break;
1156         }
1157         if (GetLastError() != ERROR_FILE_EXISTS &&
1158             GetLastError() != ERROR_SHARING_VIOLATION)
1159             return ERROR_FUNCTION_FAILED;
1160     }
1161
1162     return ERROR_SUCCESS;
1163 }
1164
1165 UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
1166 {
1167     static const WCHAR OriginalDatabase[] =
1168         {'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
1169     static const WCHAR Database[] = {'D','A','T','A','B','A','S','E',0};
1170     MSIDATABASE *db = NULL;
1171     MSIPACKAGE *package;
1172     MSIHANDLE handle;
1173     LPWSTR ptr, base_url = NULL;
1174     UINT r;
1175     WCHAR temppath[MAX_PATH], localfile[MAX_PATH], cachefile[MAX_PATH];
1176     LPCWSTR file = szPackage;
1177
1178     TRACE("%s %p\n", debugstr_w(szPackage), pPackage);
1179
1180     if( szPackage[0] == '#' )
1181     {
1182         handle = atoiW(&szPackage[1]);
1183         db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE );
1184         if( !db )
1185         {
1186             IWineMsiRemoteDatabase *remote_database;
1187
1188             remote_database = (IWineMsiRemoteDatabase *)msi_get_remote( handle );
1189             if ( !remote_database )
1190                 return ERROR_INVALID_HANDLE;
1191
1192             IWineMsiRemoteDatabase_Release( remote_database );
1193             WARN("MsiOpenPackage not allowed during a custom action!\n");
1194
1195             return ERROR_FUNCTION_FAILED;
1196         }
1197     }
1198     else
1199     {
1200         if ( UrlIsW( szPackage, URLIS_URL ) )
1201         {
1202             r = msi_download_file( szPackage, cachefile );
1203             if ( r != ERROR_SUCCESS )
1204                 return r;
1205
1206             r = copy_package_to_temp( cachefile, temppath );
1207             if ( r != ERROR_SUCCESS )
1208                 return r;
1209
1210             file = temppath;
1211
1212             base_url = strdupW( szPackage );
1213             if ( !base_url )
1214                 return ERROR_OUTOFMEMORY;
1215
1216             ptr = strrchrW( base_url, '/' );
1217             if (ptr) *(ptr + 1) = '\0';
1218         }
1219         else
1220         {
1221             r = copy_package_to_temp( szPackage, temppath );
1222             if ( r != ERROR_SUCCESS )
1223                 return r;
1224
1225             file = temppath;
1226         }
1227
1228         r = msi_get_local_package_name( localfile );
1229         if (r != ERROR_SUCCESS)
1230             return r;
1231
1232         TRACE("Copying to local package %s\n", debugstr_w(localfile));
1233
1234         if (!CopyFileW( file, localfile, FALSE ))
1235         {
1236             ERR("Unable to copy package (%s -> %s) (error %u)\n",
1237                 debugstr_w(file), debugstr_w(localfile), GetLastError());
1238             return GetLastError();
1239         }
1240
1241         TRACE("Opening relocated package %s\n", debugstr_w( file ));
1242
1243         /* transforms that add binary streams require that we open the database
1244          * read/write, which is safe because we always create a copy that is thrown
1245          * away when we're done.
1246          */
1247         r = MSI_OpenDatabaseW( file, MSIDBOPEN_DIRECT, &db );
1248         if( r != ERROR_SUCCESS )
1249         {
1250             if (file != szPackage)
1251                 DeleteFileW( file );
1252
1253             if (GetFileAttributesW(szPackage) == INVALID_FILE_ATTRIBUTES)
1254                 return ERROR_FILE_NOT_FOUND;
1255
1256             return r;
1257         }
1258
1259         db->localfile = strdupW( localfile );
1260     }
1261
1262     package = MSI_CreatePackage( db, base_url );
1263     msi_free( base_url );
1264     msiobj_release( &db->hdr );
1265     if( !package )
1266     {
1267         if (file != szPackage)
1268             DeleteFileW( file );
1269
1270         return ERROR_INSTALL_PACKAGE_INVALID;
1271     }
1272
1273     if( file != szPackage )
1274         track_tempfile( package, file );
1275
1276     MSI_SetPropertyW( package, Database, db->path );
1277
1278     if( UrlIsW( szPackage, URLIS_URL ) )
1279         MSI_SetPropertyW( package, OriginalDatabase, szPackage );
1280     else if( szPackage[0] == '#' )
1281         MSI_SetPropertyW( package, OriginalDatabase, db->path );
1282     else
1283     {
1284         WCHAR fullpath[MAX_PATH];
1285
1286         GetFullPathNameW( szPackage, MAX_PATH, fullpath, NULL );
1287         MSI_SetPropertyW( package, OriginalDatabase, fullpath );
1288     }
1289
1290     package->script = msi_alloc_zero( sizeof(MSISCRIPT) );
1291     *pPackage = package;
1292
1293     return ERROR_SUCCESS;
1294 }
1295
1296 UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
1297 {
1298     MSIPACKAGE *package = NULL;
1299     UINT ret;
1300
1301     TRACE("%s %08x %p\n", debugstr_w(szPackage), dwOptions, phPackage );
1302
1303     if( !szPackage || !phPackage )
1304         return ERROR_INVALID_PARAMETER;
1305
1306     if ( !*szPackage )
1307     {
1308         FIXME("Should create an empty database and package\n");
1309         return ERROR_FUNCTION_FAILED;
1310     }
1311
1312     if( dwOptions )
1313         FIXME("dwOptions %08x not supported\n", dwOptions);
1314
1315     ret = MSI_OpenPackageW( szPackage, &package );
1316     if( ret == ERROR_SUCCESS )
1317     {
1318         *phPackage = alloc_msihandle( &package->hdr );
1319         if (! *phPackage)
1320             ret = ERROR_NOT_ENOUGH_MEMORY;
1321         msiobj_release( &package->hdr );
1322     }
1323
1324     return ret;
1325 }
1326
1327 UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
1328 {
1329     return MsiOpenPackageExW( szPackage, 0, phPackage );
1330 }
1331
1332 UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
1333 {
1334     LPWSTR szwPack = NULL;
1335     UINT ret;
1336
1337     if( szPackage )
1338     {
1339         szwPack = strdupAtoW( szPackage );
1340         if( !szwPack )
1341             return ERROR_OUTOFMEMORY;
1342     }
1343
1344     ret = MsiOpenPackageExW( szwPack, dwOptions, phPackage );
1345
1346     msi_free( szwPack );
1347
1348     return ret;
1349 }
1350
1351 UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
1352 {
1353     return MsiOpenPackageExA( szPackage, 0, phPackage );
1354 }
1355
1356 MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
1357 {
1358     MSIPACKAGE *package;
1359     MSIHANDLE handle = 0;
1360     IUnknown *remote_unk;
1361     IWineMsiRemotePackage *remote_package;
1362
1363     TRACE("(%d)\n",hInstall);
1364
1365     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
1366     if( package)
1367     {
1368         handle = alloc_msihandle( &package->db->hdr );
1369         msiobj_release( &package->hdr );
1370     }
1371     else if ((remote_unk = msi_get_remote(hInstall)))
1372     {
1373         if (IUnknown_QueryInterface(remote_unk, &IID_IWineMsiRemotePackage,
1374                                         (LPVOID *)&remote_package) == S_OK)
1375         {
1376             IWineMsiRemotePackage_GetActiveDatabase(remote_package, &handle);
1377             IWineMsiRemotePackage_Release(remote_package);
1378         }
1379         else
1380         {
1381             WARN("remote handle %d is not a package\n", hInstall);
1382         }
1383         IUnknown_Release(remote_unk);
1384     }
1385
1386     return handle;
1387 }
1388
1389 INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType,
1390                                MSIRECORD *record)
1391 {
1392     static const WCHAR szActionData[] =
1393         {'A','c','t','i','o','n','D','a','t','a',0};
1394     static const WCHAR szSetProgress[] =
1395         {'S','e','t','P','r','o','g','r','e','s','s',0};
1396     static const WCHAR szActionText[] =
1397         {'A','c','t','i','o','n','T','e','x','t',0};
1398     DWORD log_type = 0;
1399     LPWSTR message;
1400     DWORD sz;
1401     DWORD total_size = 0;
1402     INT i;
1403     INT rc;
1404     char *msg;
1405     int len;
1406
1407     TRACE("%x\n", eMessageType);
1408     rc = 0;
1409
1410     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ERROR)
1411         log_type |= INSTALLLOGMODE_ERROR;
1412     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_WARNING)
1413         log_type |= INSTALLLOGMODE_WARNING;
1414     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_USER)
1415         log_type |= INSTALLLOGMODE_USER;
1416     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INFO)
1417         log_type |= INSTALLLOGMODE_INFO;
1418     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA)
1419         log_type |= INSTALLLOGMODE_COMMONDATA;
1420     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART)
1421         log_type |= INSTALLLOGMODE_ACTIONSTART;
1422     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONDATA)
1423         log_type |= INSTALLLOGMODE_ACTIONDATA;
1424     /* just a guess */
1425     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_PROGRESS)
1426         log_type |= 0x800;
1427
1428     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART)
1429     {
1430         static const WCHAR template_s[]=
1431             {'A','c','t','i','o','n',' ','%','s',':',' ','%','s','.',' ',0};
1432         static const WCHAR format[] = 
1433             {'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0};
1434         WCHAR timet[0x100];
1435         LPCWSTR action_text, action;
1436         LPWSTR deformatted = NULL;
1437
1438         GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, format, timet, 0x100);
1439
1440         action = MSI_RecordGetString(record, 1);
1441         action_text = MSI_RecordGetString(record, 2);
1442
1443         if (!action || !action_text)
1444             return IDOK;
1445
1446         deformat_string(package, action_text, &deformatted);
1447
1448         len = strlenW(timet) + strlenW(action) + strlenW(template_s);
1449         if (deformatted)
1450             len += strlenW(deformatted);
1451         message = msi_alloc(len*sizeof(WCHAR));
1452         sprintfW(message, template_s, timet, action);
1453         if (deformatted)
1454             strcatW(message, deformatted);
1455         msi_free(deformatted);
1456     }
1457     else
1458     {
1459         INT msg_field=1;
1460         message = msi_alloc(1*sizeof (WCHAR));
1461         message[0]=0;
1462         msg_field = MSI_RecordGetFieldCount(record);
1463         for (i = 1; i <= msg_field; i++)
1464         {
1465             LPWSTR tmp;
1466             WCHAR number[3];
1467             static const WCHAR format[] = { '%','i',':',' ',0};
1468             sz = 0;
1469             MSI_RecordGetStringW(record,i,NULL,&sz);
1470             sz+=4;
1471             total_size+=sz*sizeof(WCHAR);
1472             tmp = msi_alloc(sz*sizeof(WCHAR));
1473             message = msi_realloc(message,total_size*sizeof (WCHAR));
1474
1475             MSI_RecordGetStringW(record,i,tmp,&sz);
1476
1477             if (msg_field > 1)
1478             {
1479                 sprintfW(number,format,i);
1480                 strcatW(message,number);
1481             }
1482             strcatW(message,tmp);
1483             if (msg_field > 1)
1484                 strcatW(message, szSpace);
1485
1486             msi_free(tmp);
1487         }
1488     }
1489
1490     TRACE("%p %p %p %x %x %s\n", gUIHandlerA, gUIHandlerW, gUIHandlerRecord,
1491           gUIFilter, log_type, debugstr_w(message));
1492
1493     /* convert it to ASCII */
1494     len = WideCharToMultiByte( CP_ACP, 0, message, -1, NULL, 0, NULL, NULL );
1495     msg = msi_alloc( len );
1496     WideCharToMultiByte( CP_ACP, 0, message, -1, msg, len, NULL, NULL );
1497
1498     if (gUIHandlerW && (gUIFilter & log_type))
1499     {
1500         rc = gUIHandlerW( gUIContext, eMessageType, message );
1501     }
1502     else if (gUIHandlerA && (gUIFilter & log_type))
1503     {
1504         rc = gUIHandlerA( gUIContext, eMessageType, msg );
1505     }
1506     else if (gUIHandlerRecord && (gUIFilter & log_type))
1507     {
1508         MSIHANDLE rec = MsiCreateRecord( 1 );
1509         MsiRecordSetStringW( rec, 0, message );
1510         rc = gUIHandlerRecord( gUIContext, eMessageType, rec );
1511         MsiCloseHandle( rec );
1512     }
1513
1514     if ((!rc) && (gszLogFile[0]) && !((eMessageType & 0xff000000) ==
1515                                       INSTALLMESSAGE_PROGRESS))
1516     {
1517         DWORD write;
1518         HANDLE log_file = CreateFileW(gszLogFile,GENERIC_WRITE, 0, NULL,
1519                                   OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1520
1521         if (log_file != INVALID_HANDLE_VALUE)
1522         {
1523             SetFilePointer(log_file,0, NULL, FILE_END);
1524             WriteFile(log_file,msg,strlen(msg),&write,NULL);
1525             WriteFile(log_file,"\n",1,&write,NULL);
1526             CloseHandle(log_file);
1527         }
1528     }
1529     msi_free( msg );
1530     msi_free( message );
1531
1532     switch (eMessageType & 0xff000000)
1533     {
1534     case INSTALLMESSAGE_ACTIONDATA:
1535         /* FIXME: format record here instead of in ui_actiondata to get the
1536          * correct action data for external scripts */
1537         ControlEvent_FireSubscribedEvent(package, szActionData, record);
1538         break;
1539     case INSTALLMESSAGE_ACTIONSTART:
1540     {
1541         MSIRECORD *uirow;
1542         LPWSTR deformated;
1543         LPCWSTR action_text = MSI_RecordGetString(record, 2);
1544
1545         deformat_string(package, action_text, &deformated);
1546         uirow = MSI_CreateRecord(1);
1547         MSI_RecordSetStringW(uirow, 1, deformated);
1548         TRACE("INSTALLMESSAGE_ACTIONSTART: %s\n", debugstr_w(deformated));
1549         msi_free(deformated);
1550
1551         ControlEvent_FireSubscribedEvent(package, szActionText, uirow);
1552
1553         msiobj_release(&uirow->hdr);
1554         break;
1555     }
1556     case INSTALLMESSAGE_PROGRESS:
1557         ControlEvent_FireSubscribedEvent(package, szSetProgress, record);
1558         break;
1559     }
1560
1561     return ERROR_SUCCESS;
1562 }
1563
1564 INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
1565                               MSIHANDLE hRecord)
1566 {
1567     UINT ret = ERROR_INVALID_HANDLE;
1568     MSIPACKAGE *package = NULL;
1569     MSIRECORD *record = NULL;
1570
1571     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
1572     if( !package )
1573     {
1574         HRESULT hr;
1575         IWineMsiRemotePackage *remote_package;
1576
1577         remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
1578         if (!remote_package)
1579             return ERROR_INVALID_HANDLE;
1580
1581         hr = IWineMsiRemotePackage_ProcessMessage( remote_package, eMessageType, hRecord );
1582
1583         IWineMsiRemotePackage_Release( remote_package );
1584
1585         if (FAILED(hr))
1586         {
1587             if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1588                 return HRESULT_CODE(hr);
1589
1590             return ERROR_FUNCTION_FAILED;
1591         }
1592
1593         return ERROR_SUCCESS;
1594     }
1595
1596     record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD );
1597     if( !record )
1598         goto out;
1599
1600     ret = MSI_ProcessMessage( package, eMessageType, record );
1601
1602 out:
1603     msiobj_release( &package->hdr );
1604     if( record )
1605         msiobj_release( &record->hdr );
1606
1607     return ret;
1608 }
1609
1610 /* property code */
1611
1612 UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue )
1613 {
1614     LPWSTR szwName = NULL, szwValue = NULL;
1615     UINT r = ERROR_OUTOFMEMORY;
1616
1617     szwName = strdupAtoW( szName );
1618     if( szName && !szwName )
1619         goto end;
1620
1621     szwValue = strdupAtoW( szValue );
1622     if( szValue && !szwValue )
1623         goto end;
1624
1625     r = MsiSetPropertyW( hInstall, szwName, szwValue);
1626
1627 end:
1628     msi_free( szwName );
1629     msi_free( szwValue );
1630
1631     return r;
1632 }
1633
1634 static void msi_reset_folders( MSIPACKAGE *package, BOOL source )
1635 {
1636     MSIFOLDER *folder;
1637
1638     LIST_FOR_EACH_ENTRY( folder, &package->folders, MSIFOLDER, entry )
1639     {
1640         if ( source )
1641         {
1642             msi_free( folder->ResolvedSource );
1643             folder->ResolvedSource = NULL;
1644         }
1645         else
1646         {
1647             msi_free( folder->ResolvedTarget );
1648             folder->ResolvedTarget = NULL;
1649         }
1650     }
1651 }
1652
1653 UINT MSI_SetPropertyW( MSIPACKAGE *package, LPCWSTR szName, LPCWSTR szValue)
1654 {
1655     MSIQUERY *view;
1656     MSIRECORD *row = NULL;
1657     UINT rc;
1658     DWORD sz = 0;
1659     WCHAR Query[1024];
1660
1661     static const WCHAR Insert[] = {
1662         'I','N','S','E','R','T',' ','i','n','t','o',' ',
1663         '`','_','P','r','o','p','e','r','t','y','`',' ','(',
1664         '`','_','P','r','o','p','e','r','t','y','`',',',
1665         '`','V','a','l','u','e','`',')',' ','V','A','L','U','E','S'
1666         ,' ','(','?',',','?',')',0};
1667     static const WCHAR Update[] = {
1668         'U','P','D','A','T','E',' ','`','_','P','r','o','p','e','r','t','y','`',
1669         ' ','s','e','t',' ','`','V','a','l','u','e','`',' ','=',' ','?',' ',
1670         'w','h','e','r','e',' ','`','_','P','r','o','p','e','r','t','y','`',
1671         ' ','=',' ','\'','%','s','\'',0};
1672     static const WCHAR Delete[] = {
1673         'D','E','L','E','T','E',' ','F','R','O','M',' ',
1674         '`','_','P','r','o','p','e','r','t','y','`',' ','W','H','E','R','E',' ',
1675         '`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0};
1676
1677     TRACE("%p %s %s\n", package, debugstr_w(szName), debugstr_w(szValue));
1678
1679     if (!szName)
1680         return ERROR_INVALID_PARAMETER;
1681
1682     /* this one is weird... */
1683     if (!szName[0])
1684         return szValue ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS;
1685
1686     rc = MSI_GetPropertyW(package, szName, 0, &sz);
1687     if (!szValue || !*szValue)
1688     {
1689         sprintfW(Query, Delete, szName);
1690     }
1691     else if (rc == ERROR_MORE_DATA || rc == ERROR_SUCCESS)
1692     {
1693         sprintfW(Query, Update, szName);
1694
1695         row = MSI_CreateRecord(1);
1696         MSI_RecordSetStringW(row, 1, szValue);
1697     }
1698     else
1699     {
1700         strcpyW(Query, Insert);
1701
1702         row = MSI_CreateRecord(2);
1703         MSI_RecordSetStringW(row, 1, szName);
1704         MSI_RecordSetStringW(row, 2, szValue);
1705     }
1706
1707     rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
1708     if (rc == ERROR_SUCCESS)
1709     {
1710         rc = MSI_ViewExecute(view, row);
1711         MSI_ViewClose(view);
1712         msiobj_release(&view->hdr);
1713     }
1714
1715     if (row)
1716       msiobj_release(&row->hdr);
1717
1718     if (rc == ERROR_SUCCESS && (!lstrcmpW(szName, cszSourceDir)))
1719         msi_reset_folders(package, TRUE);
1720
1721     return rc;
1722 }
1723
1724 UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue)
1725 {
1726     MSIPACKAGE *package;
1727     UINT ret;
1728
1729     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
1730     if( !package )
1731     {
1732         HRESULT hr;
1733         BSTR name = NULL, value = NULL;
1734         IWineMsiRemotePackage *remote_package;
1735
1736         remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
1737         if (!remote_package)
1738             return ERROR_INVALID_HANDLE;
1739
1740         name = SysAllocString( szName );
1741         value = SysAllocString( szValue );
1742         if ((!name && szName) || (!value && szValue))
1743         {
1744             SysFreeString( name );
1745             SysFreeString( value );
1746             IWineMsiRemotePackage_Release( remote_package );
1747             return ERROR_OUTOFMEMORY;
1748         }
1749
1750         hr = IWineMsiRemotePackage_SetProperty( remote_package, name, value );
1751
1752         SysFreeString( name );
1753         SysFreeString( value );
1754         IWineMsiRemotePackage_Release( remote_package );
1755
1756         if (FAILED(hr))
1757         {
1758             if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1759                 return HRESULT_CODE(hr);
1760
1761             return ERROR_FUNCTION_FAILED;
1762         }
1763
1764         return ERROR_SUCCESS;
1765     }
1766
1767     ret = MSI_SetPropertyW( package, szName, szValue);
1768     msiobj_release( &package->hdr );
1769     return ret;
1770 }
1771
1772 static MSIRECORD *MSI_GetPropertyRow( MSIPACKAGE *package, LPCWSTR name )
1773 {
1774     MSIQUERY *view;
1775     MSIRECORD *rec, *row = NULL;
1776     UINT r;
1777
1778     static const WCHAR query[]= {
1779         'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ',
1780         'F','R','O','M',' ' ,'`','_','P','r','o','p','e','r','t','y','`',
1781         ' ','W','H','E','R','E',' ' ,'`','_','P','r','o','p','e','r','t','y','`',
1782         '=','?',0};
1783
1784     if (!name || !*name)
1785         return NULL;
1786
1787     rec = MSI_CreateRecord(1);
1788     if (!rec)
1789         return NULL;
1790
1791     MSI_RecordSetStringW(rec, 1, name);
1792
1793     r = MSI_DatabaseOpenViewW(package->db, query, &view);
1794     if (r == ERROR_SUCCESS)
1795     {
1796         MSI_ViewExecute(view, rec);
1797         MSI_ViewFetch(view, &row);
1798         MSI_ViewClose(view);
1799         msiobj_release(&view->hdr);
1800     }
1801
1802     msiobj_release(&rec->hdr);
1803     return row;
1804 }
1805
1806 /* internal function, not compatible with MsiGetPropertyW */
1807 UINT MSI_GetPropertyW( MSIPACKAGE *package, LPCWSTR szName, 
1808                        LPWSTR szValueBuf, LPDWORD pchValueBuf )
1809 {
1810     MSIRECORD *row;
1811     UINT rc = ERROR_FUNCTION_FAILED;
1812
1813     row = MSI_GetPropertyRow( package, szName );
1814
1815     if (*pchValueBuf > 0)
1816         szValueBuf[0] = 0;
1817
1818     if (row)
1819     {
1820         rc = MSI_RecordGetStringW(row, 1, szValueBuf, pchValueBuf);
1821         msiobj_release(&row->hdr);
1822     }
1823
1824     if (rc == ERROR_SUCCESS)
1825         TRACE("returning %s for property %s\n", debugstr_w(szValueBuf),
1826             debugstr_w(szName));
1827     else if (rc == ERROR_MORE_DATA)
1828         TRACE("need %d sized buffer for %s\n", *pchValueBuf,
1829             debugstr_w(szName));
1830     else
1831     {
1832         *pchValueBuf = 0;
1833         TRACE("property %s not found\n", debugstr_w(szName));
1834     }
1835
1836     return rc;
1837 }
1838
1839 LPWSTR msi_dup_property(MSIPACKAGE *package, LPCWSTR prop)
1840 {
1841     DWORD sz = 0;
1842     LPWSTR str;
1843     UINT r;
1844
1845     r = MSI_GetPropertyW(package, prop, NULL, &sz);
1846     if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
1847         return NULL;
1848
1849     sz++;
1850     str = msi_alloc(sz * sizeof(WCHAR));
1851     r = MSI_GetPropertyW(package, prop, str, &sz);
1852     if (r != ERROR_SUCCESS)
1853     {
1854         msi_free(str);
1855         str = NULL;
1856     }
1857
1858     return str;
1859 }
1860
1861 int msi_get_property_int(MSIPACKAGE *package, LPCWSTR prop, int def)
1862 {
1863     LPWSTR str = msi_dup_property(package, prop);
1864     int val = str ? atoiW(str) : def;
1865     msi_free(str);
1866     return val;
1867 }
1868
1869 static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name,
1870                              awstring *szValueBuf, LPDWORD pchValueBuf )
1871 {
1872     MSIPACKAGE *package;
1873     MSIRECORD *row = NULL;
1874     UINT r = ERROR_FUNCTION_FAILED;
1875     LPCWSTR val = NULL;
1876
1877     TRACE("%u %s %p %p\n", handle, debugstr_w(name),
1878           szValueBuf->str.w, pchValueBuf );
1879
1880     if (!name)
1881         return ERROR_INVALID_PARAMETER;
1882
1883     package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE );
1884     if (!package)
1885     {
1886         HRESULT hr;
1887         IWineMsiRemotePackage *remote_package;
1888         LPWSTR value = NULL;
1889         BSTR bname;
1890         DWORD len;
1891
1892         remote_package = (IWineMsiRemotePackage *)msi_get_remote( handle );
1893         if (!remote_package)
1894             return ERROR_INVALID_HANDLE;
1895
1896         bname = SysAllocString( name );
1897         if (!bname)
1898         {
1899             IWineMsiRemotePackage_Release( remote_package );
1900             return ERROR_OUTOFMEMORY;
1901         }
1902
1903         len = 0;
1904         hr = IWineMsiRemotePackage_GetProperty( remote_package, bname, NULL, &len );
1905         if (FAILED(hr))
1906             goto done;
1907
1908         len++;
1909         value = msi_alloc(len * sizeof(WCHAR));
1910         if (!value)
1911         {
1912             r = ERROR_OUTOFMEMORY;
1913             goto done;
1914         }
1915
1916         hr = IWineMsiRemotePackage_GetProperty( remote_package, bname, (BSTR *)value, &len );
1917         if (FAILED(hr))
1918             goto done;
1919
1920         r = msi_strcpy_to_awstring( value, szValueBuf, pchValueBuf );
1921
1922         /* Bug required by Adobe installers */
1923         if (!szValueBuf->unicode && !szValueBuf->str.a)
1924             *pchValueBuf *= sizeof(WCHAR);
1925
1926 done:
1927         IWineMsiRemotePackage_Release(remote_package);
1928         SysFreeString(bname);
1929         msi_free(value);
1930
1931         if (FAILED(hr))
1932         {
1933             if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1934                 return HRESULT_CODE(hr);
1935
1936             return ERROR_FUNCTION_FAILED;
1937         }
1938
1939         return r;
1940     }
1941
1942     row = MSI_GetPropertyRow( package, name );
1943     if (row)
1944         val = MSI_RecordGetString( row, 1 );
1945
1946     if (!val)
1947         val = szEmpty;
1948
1949     r = msi_strcpy_to_awstring( val, szValueBuf, pchValueBuf );
1950
1951     if (row)
1952         msiobj_release( &row->hdr );
1953     msiobj_release( &package->hdr );
1954
1955     return r;
1956 }
1957
1958 UINT WINAPI MsiGetPropertyA( MSIHANDLE hInstall, LPCSTR szName,
1959                              LPSTR szValueBuf, LPDWORD pchValueBuf )
1960 {
1961     awstring val;
1962     LPWSTR name;
1963     UINT r;
1964
1965     val.unicode = FALSE;
1966     val.str.a = szValueBuf;
1967
1968     name = strdupAtoW( szName );
1969     if (szName && !name)
1970         return ERROR_OUTOFMEMORY;
1971
1972     r = MSI_GetProperty( hInstall, name, &val, pchValueBuf );
1973     msi_free( name );
1974     return r;
1975 }
1976
1977 UINT WINAPI MsiGetPropertyW( MSIHANDLE hInstall, LPCWSTR szName,
1978                              LPWSTR szValueBuf, LPDWORD pchValueBuf )
1979 {
1980     awstring val;
1981
1982     val.unicode = TRUE;
1983     val.str.w = szValueBuf;
1984
1985     return MSI_GetProperty( hInstall, szName, &val, pchValueBuf );
1986 }
1987
1988 typedef struct _msi_remote_package_impl {
1989     const IWineMsiRemotePackageVtbl *lpVtbl;
1990     MSIHANDLE package;
1991     LONG refs;
1992 } msi_remote_package_impl;
1993
1994 static inline msi_remote_package_impl* mrp_from_IWineMsiRemotePackage( IWineMsiRemotePackage* iface )
1995 {
1996     return (msi_remote_package_impl*) iface;
1997 }
1998
1999 static HRESULT WINAPI mrp_QueryInterface( IWineMsiRemotePackage *iface,
2000                 REFIID riid,LPVOID *ppobj)
2001 {
2002     if( IsEqualCLSID( riid, &IID_IUnknown ) ||
2003         IsEqualCLSID( riid, &IID_IWineMsiRemotePackage ) )
2004     {
2005         IUnknown_AddRef( iface );
2006         *ppobj = iface;
2007         return S_OK;
2008     }
2009
2010     return E_NOINTERFACE;
2011 }
2012
2013 static ULONG WINAPI mrp_AddRef( IWineMsiRemotePackage *iface )
2014 {
2015     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2016
2017     return InterlockedIncrement( &This->refs );
2018 }
2019
2020 static ULONG WINAPI mrp_Release( IWineMsiRemotePackage *iface )
2021 {
2022     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2023     ULONG r;
2024
2025     r = InterlockedDecrement( &This->refs );
2026     if (r == 0)
2027     {
2028         MsiCloseHandle( This->package );
2029         msi_free( This );
2030     }
2031     return r;
2032 }
2033
2034 static HRESULT WINAPI mrp_SetMsiHandle( IWineMsiRemotePackage *iface, MSIHANDLE handle )
2035 {
2036     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2037     This->package = handle;
2038     return S_OK;
2039 }
2040
2041 static HRESULT WINAPI mrp_GetActiveDatabase( IWineMsiRemotePackage *iface, MSIHANDLE *handle )
2042 {
2043     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2044     IWineMsiRemoteDatabase *rdb = NULL;
2045     HRESULT hr;
2046     MSIHANDLE hdb;
2047
2048     hr = create_msi_remote_database( NULL, (LPVOID *)&rdb );
2049     if (FAILED(hr) || !rdb)
2050     {
2051         ERR("Failed to create remote database\n");
2052         return hr;
2053     }
2054
2055     hdb = MsiGetActiveDatabase(This->package);
2056
2057     hr = IWineMsiRemoteDatabase_SetMsiHandle( rdb, hdb );
2058     if (FAILED(hr))
2059     {
2060         ERR("Failed to set the database handle\n");
2061         return hr;
2062     }
2063
2064     *handle = alloc_msi_remote_handle( (IUnknown *)rdb );
2065     return S_OK;
2066 }
2067
2068 static HRESULT WINAPI mrp_GetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR *value, DWORD *size )
2069 {
2070     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2071     UINT r;
2072
2073     r = MsiGetPropertyW(This->package, (LPWSTR)property, (LPWSTR)value, size);
2074     if (r != ERROR_SUCCESS)
2075         return HRESULT_FROM_WIN32(r);
2076
2077     return S_OK;
2078 }
2079
2080 static HRESULT WINAPI mrp_SetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR value )
2081 {
2082     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2083     UINT r = MsiSetPropertyW(This->package, property, value);
2084     return HRESULT_FROM_WIN32(r);
2085 }
2086
2087 static HRESULT WINAPI mrp_ProcessMessage( IWineMsiRemotePackage *iface, INSTALLMESSAGE message, MSIHANDLE record )
2088 {
2089     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2090     UINT r = MsiProcessMessage(This->package, message, record);
2091     return HRESULT_FROM_WIN32(r);
2092 }
2093
2094 static HRESULT WINAPI mrp_DoAction( IWineMsiRemotePackage *iface, BSTR action )
2095 {
2096     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2097     UINT r = MsiDoActionW(This->package, action);
2098     return HRESULT_FROM_WIN32(r);
2099 }
2100
2101 static HRESULT WINAPI mrp_Sequence( IWineMsiRemotePackage *iface, BSTR table, int sequence )
2102 {
2103     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2104     UINT r = MsiSequenceW(This->package, table, sequence);
2105     return HRESULT_FROM_WIN32(r);
2106 }
2107
2108 static HRESULT WINAPI mrp_GetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR *value, DWORD *size )
2109 {
2110     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2111     UINT r = MsiGetTargetPathW(This->package, (LPWSTR)folder, (LPWSTR)value, size);
2112     return HRESULT_FROM_WIN32(r);
2113 }
2114
2115 static HRESULT WINAPI mrp_SetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR value)
2116 {
2117     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2118     UINT r = MsiSetTargetPathW(This->package, folder, value);
2119     return HRESULT_FROM_WIN32(r);
2120 }
2121
2122 static HRESULT WINAPI mrp_GetSourcePath( IWineMsiRemotePackage *iface, BSTR folder, BSTR *value, DWORD *size )
2123 {
2124     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2125     UINT r = MsiGetSourcePathW(This->package, (LPWSTR)folder, (LPWSTR)value, size);
2126     return HRESULT_FROM_WIN32(r);
2127 }
2128
2129 static HRESULT WINAPI mrp_GetMode( IWineMsiRemotePackage *iface, MSIRUNMODE mode, BOOL *ret )
2130 {
2131     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2132     *ret = MsiGetMode(This->package, mode);
2133     return S_OK;
2134 }
2135
2136 static HRESULT WINAPI mrp_SetMode( IWineMsiRemotePackage *iface, MSIRUNMODE mode, BOOL state )
2137 {
2138     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2139     UINT r = MsiSetMode(This->package, mode, state);
2140     return HRESULT_FROM_WIN32(r);
2141 }
2142
2143 static HRESULT WINAPI mrp_GetFeatureState( IWineMsiRemotePackage *iface, BSTR feature,
2144                                     INSTALLSTATE *installed, INSTALLSTATE *action )
2145 {
2146     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2147     UINT r = MsiGetFeatureStateW(This->package, feature, installed, action);
2148     return HRESULT_FROM_WIN32(r);
2149 }
2150
2151 static HRESULT WINAPI mrp_SetFeatureState( IWineMsiRemotePackage *iface, BSTR feature, INSTALLSTATE state )
2152 {
2153     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2154     UINT r = MsiSetFeatureStateW(This->package, feature, state);
2155     return HRESULT_FROM_WIN32(r);
2156 }
2157
2158 static HRESULT WINAPI mrp_GetComponentState( IWineMsiRemotePackage *iface, BSTR component,
2159                                       INSTALLSTATE *installed, INSTALLSTATE *action )
2160 {
2161     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2162     UINT r = MsiGetComponentStateW(This->package, component, installed, action);
2163     return HRESULT_FROM_WIN32(r);
2164 }
2165
2166 static HRESULT WINAPI mrp_SetComponentState( IWineMsiRemotePackage *iface, BSTR component, INSTALLSTATE state )
2167 {
2168     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2169     UINT r = MsiSetComponentStateW(This->package, component, state);
2170     return HRESULT_FROM_WIN32(r);
2171 }
2172
2173 static HRESULT WINAPI mrp_GetLanguage( IWineMsiRemotePackage *iface, LANGID *language )
2174 {
2175     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2176     *language = MsiGetLanguage(This->package);
2177     return S_OK;
2178 }
2179
2180 static HRESULT WINAPI mrp_SetInstallLevel( IWineMsiRemotePackage *iface, int level )
2181 {
2182     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2183     UINT r = MsiSetInstallLevel(This->package, level);
2184     return HRESULT_FROM_WIN32(r);
2185 }
2186
2187 static HRESULT WINAPI mrp_FormatRecord( IWineMsiRemotePackage *iface, MSIHANDLE record,
2188                                         BSTR *value)
2189 {
2190     DWORD size = 0;
2191     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2192     UINT r = MsiFormatRecordW(This->package, record, NULL, &size);
2193     if (r == ERROR_SUCCESS)
2194     {
2195         *value = SysAllocStringLen(NULL, size);
2196         if (!*value)
2197             return E_OUTOFMEMORY;
2198         size++;
2199         r = MsiFormatRecordW(This->package, record, *value, &size);
2200     }
2201     return HRESULT_FROM_WIN32(r);
2202 }
2203
2204 static HRESULT WINAPI mrp_EvaluateCondition( IWineMsiRemotePackage *iface, BSTR condition )
2205 {
2206     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2207     UINT r = MsiEvaluateConditionW(This->package, condition);
2208     return HRESULT_FROM_WIN32(r);
2209 }
2210
2211 static HRESULT WINAPI mrp_GetFeatureCost( IWineMsiRemotePackage *iface, BSTR feature,
2212                                           INT cost_tree, INSTALLSTATE state, INT *cost )
2213 {
2214     msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface );
2215     UINT r = MsiGetFeatureCostW(This->package, feature, cost_tree, state, cost);
2216     return HRESULT_FROM_WIN32(r);
2217 }
2218
2219 static const IWineMsiRemotePackageVtbl msi_remote_package_vtbl =
2220 {
2221     mrp_QueryInterface,
2222     mrp_AddRef,
2223     mrp_Release,
2224     mrp_SetMsiHandle,
2225     mrp_GetActiveDatabase,
2226     mrp_GetProperty,
2227     mrp_SetProperty,
2228     mrp_ProcessMessage,
2229     mrp_DoAction,
2230     mrp_Sequence,
2231     mrp_GetTargetPath,
2232     mrp_SetTargetPath,
2233     mrp_GetSourcePath,
2234     mrp_GetMode,
2235     mrp_SetMode,
2236     mrp_GetFeatureState,
2237     mrp_SetFeatureState,
2238     mrp_GetComponentState,
2239     mrp_SetComponentState,
2240     mrp_GetLanguage,
2241     mrp_SetInstallLevel,
2242     mrp_FormatRecord,
2243     mrp_EvaluateCondition,
2244     mrp_GetFeatureCost,
2245 };
2246
2247 HRESULT create_msi_remote_package( IUnknown *pOuter, LPVOID *ppObj )
2248 {
2249     msi_remote_package_impl* This;
2250
2251     This = msi_alloc( sizeof *This );
2252     if (!This)
2253         return E_OUTOFMEMORY;
2254
2255     This->lpVtbl = &msi_remote_package_vtbl;
2256     This->package = 0;
2257     This->refs = 1;
2258
2259     *ppObj = This;
2260
2261     return S_OK;
2262 }
2263
2264 UINT msi_package_add_info(MSIPACKAGE *package, DWORD context, DWORD options,
2265                           LPCWSTR property, LPWSTR value)
2266 {
2267     MSISOURCELISTINFO *info;
2268
2269     info = msi_alloc(sizeof(MSISOURCELISTINFO));
2270     if (!info)
2271         return ERROR_OUTOFMEMORY;
2272
2273     info->context = context;
2274     info->options = options;
2275     info->property = property;
2276     info->value = strdupW(value);
2277     list_add_head(&package->sourcelist_info, &info->entry);
2278
2279     return ERROR_SUCCESS;
2280 }
2281
2282 UINT msi_package_add_media_disk(MSIPACKAGE *package, DWORD context, DWORD options,
2283                                 DWORD disk_id, LPWSTR volume_label, LPWSTR disk_prompt)
2284 {
2285     MSIMEDIADISK *disk;
2286
2287     disk = msi_alloc(sizeof(MSIMEDIADISK));
2288     if (!disk)
2289         return ERROR_OUTOFMEMORY;
2290
2291     disk->context = context;
2292     disk->options = options;
2293     disk->disk_id = disk_id;
2294     disk->volume_label = strdupW(volume_label);
2295     disk->disk_prompt = strdupW(disk_prompt);
2296     list_add_head(&package->sourcelist_media, &disk->entry);
2297
2298     return ERROR_SUCCESS;
2299 }