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