Dump DirectSound capabilities flags.
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #define NONAMELESSUNION
22
23 #include <stdarg.h>
24 #include <stdio.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winreg.h"
28 #include "winnls.h"
29 #include "shlwapi.h"
30 #include "wine/debug.h"
31 #include "msi.h"
32 #include "msiquery.h"
33 #include "msipriv.h"
34 #include "objidl.h"
35 #include "wincrypt.h"
36 #include "winuser.h"
37 #include "shlobj.h"
38 #include "wine/unicode.h"
39 #include "objbase.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(msi);
42
43 /*
44  * The MSVC headers define the MSIDBOPEN_* macros cast to LPCTSTR,
45  *  which is a problem because LPCTSTR isn't defined when compiling wine.
46  * To work around this problem, we need to define LPCTSTR as LPCWSTR here,
47  *  and make sure to only use it in W functions.
48  */
49 #define LPCTSTR LPCWSTR
50
51 void MSI_FreePackage( MSIOBJECTHDR *arg)
52 {
53     MSIPACKAGE *package= (MSIPACKAGE*) arg;
54
55     ACTION_remove_tracked_tempfiles(package);
56
57     if (package->features && package->loaded_features > 0)
58         HeapFree(GetProcessHeap(),0,package->features);
59
60     if (package->folders && package->loaded_folders > 0)
61         HeapFree(GetProcessHeap(),0,package->folders);
62     
63     if (package->components && package->loaded_components > 0)
64         HeapFree(GetProcessHeap(),0,package->components);
65
66     if (package->files && package->loaded_files > 0)
67         HeapFree(GetProcessHeap(),0,package->files);
68     msiobj_release( &package->db->hdr );
69 }
70
71 UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
72 {
73     LPWSTR szwPack = NULL;
74     UINT len, ret;
75
76     TRACE("%s %p\n",debugstr_a(szPackage), phPackage);
77
78     if( szPackage )
79     {
80         len = MultiByteToWideChar( CP_ACP, 0, szPackage, -1, NULL, 0 );
81         szwPack = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
82         if( szwPack )
83             MultiByteToWideChar( CP_ACP, 0, szPackage, -1, szwPack, len );
84     }
85
86     ret = MsiOpenPackageW( szwPack, phPackage );
87
88     if( szwPack )
89         HeapFree( GetProcessHeap(), 0, szwPack );
90
91     return ret;
92 }
93
94
95 static const UINT clone_properties(MSIDATABASE *db)
96 {
97     MSIQUERY * view = NULL;
98     UINT rc;
99     static const WCHAR CreateSql[] = {
100        'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','_','P','r','o',
101        'p','e','r','t','y','`',' ','(',' ','`','_','P','r','o','p','e','r','t',
102        'y','`',' ','C','H','A','R','(','5','6',')',' ','N','O','T',' ','N','U',
103        'L','L',',',' ','`','V','a','l','u','e','`',' ','C','H','A','R','(','9',
104        '8',')',' ','N','O','T',' ','N','U','L','L',' ','P','R','I','M','A','R',
105        'Y',' ','K','E','Y',' ','`','_','P','r','o','p','e','r','t','y','`',')',0};
106     static const WCHAR Query[] = {
107        'S','E','L','E','C','T',' ','*',' ',
108        'f','r','o','m',' ','P','r','o','p','e','r','t','y',0};
109     static const WCHAR Insert[] = {
110        'I','N','S','E','R','T',' ','i','n','t','o',' ',
111        '`','_','P','r','o','p','e','r','t','y','`',' ',
112        '(','`','_','P','r','o','p','e','r','t','y','`',',',
113        '`','V','a','l','u','e','`',')',' ',
114        'V','A','L','U','E','S',' ','(','?',')',0};
115
116     /* create the temporary properties table */
117     rc = MSI_DatabaseOpenViewW(db, CreateSql, &view);
118     if (rc != ERROR_SUCCESS)
119         return rc;
120     rc = MSI_ViewExecute(view,0);   
121     MSI_ViewClose(view);
122     msiobj_release(&view->hdr); 
123     if (rc != ERROR_SUCCESS)
124         return rc;
125
126     /* clone the existing properties */
127     rc = MSI_DatabaseOpenViewW(db, Query, &view);
128     if (rc != ERROR_SUCCESS)
129         return rc;
130
131     rc = MSI_ViewExecute(view, 0);
132     if (rc != ERROR_SUCCESS)
133     {
134         MSI_ViewClose(view);
135         msiobj_release(&view->hdr); 
136         return rc;
137     }
138     while (1)
139     {
140         MSIRECORD * row;
141         MSIQUERY * view2;
142
143         rc = MSI_ViewFetch(view,&row);
144         if (rc != ERROR_SUCCESS)
145             break;
146
147         rc = MSI_DatabaseOpenViewW(db,Insert,&view2);  
148         if (rc!= ERROR_SUCCESS)
149             continue;
150         rc = MSI_ViewExecute(view2,row);
151         MSI_ViewClose(view2);
152         msiobj_release(&view2->hdr);
153  
154         if (rc == ERROR_SUCCESS) 
155             msiobj_release(&row->hdr); 
156     }
157     MSI_ViewClose(view);
158     msiobj_release(&view->hdr);
159     
160     return rc;
161 }
162
163 /*
164  * There are a whole slew of these we need to set
165  *
166  *
167 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/properties.asp
168  */
169 static VOID set_installer_properties(MSIPACKAGE *package)
170 {
171     WCHAR pth[MAX_PATH];
172     OSVERSIONINFOA OSVersion;
173     DWORD verval;
174     WCHAR verstr[10], msiver[10];
175
176     static const WCHAR cszbs[]={'\\',0};
177     static const WCHAR CFF[] = 
178 {'C','o','m','m','o','n','F','i','l','e','s','F','o','l','d','e','r',0};
179     static const WCHAR PFF[] = 
180 {'P','r','o','g','r','a','m','F','i','l','e','s','F','o','l','d','e','r',0};
181     static const WCHAR CADF[] = 
182 {'C','o','m','m','o','n','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
183     static const WCHAR ATF[] = 
184 {'A','d','m','i','n','T','o','o','l','s','F','o','l','d','e','r',0};
185     static const WCHAR ADF[] = 
186 {'A','p','p','D','a','t','a','F','o','l','d','e','r',0};
187     static const WCHAR SF[] = 
188 {'S','y','s','t','e','m','F','o','l','d','e','r',0};
189     static const WCHAR LADF[] = 
190 {'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
191     static const WCHAR MPF[] = 
192 {'M','y','P','i','c','t','u','r','e','s','F','o','l','d','e','r',0};
193     static const WCHAR PF[] = 
194 {'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0};
195     static const WCHAR WF[] = 
196 {'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
197     static const WCHAR TF[]=
198 {'T','e','m','p','F','o','l','d','e','r',0};
199     static const WCHAR szAdminUser[] =
200 {'A','d','m','i','n','U','s','e','r',0};
201     static const WCHAR szPriv[] =
202 {'P','r','i','v','i','l','e','g','e','d',0};
203     static const WCHAR szOne[] =
204 {'1',0};
205     static const WCHAR v9x[] = { 'V','e','r','s','i','o','n','9','X',0 };
206     static const WCHAR vNT[] = { 'V','e','r','s','i','o','n','N','T',0 };
207     static const WCHAR szFormat[] = {'%','l','i',0};
208     static const WCHAR szWinBuild[] =
209 {'W','i','n','d','o','w','s','B','u','i','l','d', 0 };
210     static const WCHAR szSPL[] = 
211 {'S','e','r','v','i','c','e','P','a','c','k','L','e','v','e','l',0 };
212     static const WCHAR szSix[] = {'6',0 };
213
214     static const WCHAR szVersionMsi[] = { 'V','e','r','s','i','o','n','M','s','i',0 };
215     static const WCHAR szFormat2[] = {'%','l','i','.','%','l','i',0};
216
217 /* these need to be dynamically discovered sometime */
218
219     static const WCHAR ProgramMenuFolder[] = 
220 {'P','r','o','g','r','a','m','M','e','n','u','F','o','l','d','e','r',0};
221     static const WCHAR PMFPath[] = 
222 {'C',':','\\','W','i','n','d','o','w','s','\\','S','t','a','r','t',' ',
223 'M','e','n','u','\\','P','r','o','g','r','a','m','s','\\',0};
224     static const WCHAR FavoritesFolder[] = 
225 {'F','a','v','o','r','i','t','e','s','F','o','l','d','e','r',0};
226     static const WCHAR FFPath[] = 
227 {'C',':','\\','W','i','n','d','o','w','s','\\',
228 'F','a','v','o','r','i','t','e','s','\\',0};
229     static const WCHAR FontsFolder[] = 
230 {'F','o','n','t','s','F','o','l','d','e','r',0};
231     static const WCHAR FoFPath[] = 
232 {'C',':','\\','W','i','n','d','o','w','s','\\','F','o','n','t','s','\\',0};
233     static const WCHAR SendToFolder[] = 
234 {'S','e','n','d','T','o','F','o','l','d','e','r',0};
235     static const WCHAR STFPath[] = 
236 {'C',':','\\','W','i','n','d','o','w','s','\\','S','e','n','d','T','o','\\',0};
237     static const WCHAR StartMenuFolder[] = 
238 {'S','t','a','r','t','M','e','n','u','F','o','l','d','e','r',0};
239     static const WCHAR SMFPath[] = 
240 {'C',':','\\','W','i','n','d','o','w','s','\\','S','t','a','r','t',' ',
241 'M','e','n','u','\\',0};
242     static const WCHAR StartupFolder[] = 
243 {'S','t','a','r','t','u','p','F','o','l','d','e','r',0};
244     static const WCHAR SFPath[] = 
245 {'C',':','\\','W','i','n','d','o','w','s','\\','S','t','a','r','t',' ',
246 'M','e','n','u','\\','P','r','o','g','r','a','m','s','\\',
247 'S','t','a','r','t','u','p','\\',0};
248     static const WCHAR TemplateFolder[] = 
249 {'T','e','m','p','l','a','t','e','F','o','l','d','e','r',0};
250     static const WCHAR TFPath[] = 
251 {'C',':','\\','W','i','n','d','o','w','s','\\',
252 'S','h','e','l','l','N','e','w','\\',0};
253     static const WCHAR DesktopFolder[] = 
254 {'D','e','s','k','t','o','p','F','o','l','d','e','r',0};
255     static const WCHAR DFPath[] = 
256 {'C',':','\\','W','i','n','d','o','w','s','\\',
257 'D','e','s','k','t','o','p','\\',0};
258
259 /*
260  * Other things I notice set
261  *
262 ScreenY
263 ScreenX
264 SystemLanguageID
265 ComputerName
266 UserLanguageID
267 LogonUser
268 VirtualMemory
269 PhysicalMemory
270 Intel
271 ShellAdvSupport
272 DefaultUIFont
273 VersionDatabase
274 PackagecodeChanging
275 ProductState
276 CaptionHeight
277 BorderTop
278 BorderSide
279 TextHeight
280 ColorBits
281 RedirectedDllSupport
282 Time
283 Date
284 Privileged
285 */
286
287     SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES_COMMON,NULL,0,pth);
288     strcatW(pth,cszbs);
289     MSI_SetPropertyW(package, CFF, pth);
290
291     SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES,NULL,0,pth);
292     strcatW(pth,cszbs);
293     MSI_SetPropertyW(package, PFF, pth);
294
295     SHGetFolderPathW(NULL,CSIDL_COMMON_APPDATA,NULL,0,pth);
296     strcatW(pth,cszbs);
297     MSI_SetPropertyW(package, CADF, pth);
298
299     SHGetFolderPathW(NULL,CSIDL_ADMINTOOLS,NULL,0,pth);
300     strcatW(pth,cszbs);
301     MSI_SetPropertyW(package, ATF, pth);
302
303     SHGetFolderPathW(NULL,CSIDL_APPDATA,NULL,0,pth);
304     strcatW(pth,cszbs);
305     MSI_SetPropertyW(package, ADF, pth);
306
307     SHGetFolderPathW(NULL,CSIDL_SYSTEM,NULL,0,pth);
308     strcatW(pth,cszbs);
309     MSI_SetPropertyW(package, SF, pth);
310
311     SHGetFolderPathW(NULL,CSIDL_LOCAL_APPDATA,NULL,0,pth);
312     strcatW(pth,cszbs);
313     MSI_SetPropertyW(package, LADF, pth);
314
315     SHGetFolderPathW(NULL,CSIDL_MYPICTURES,NULL,0,pth);
316     strcatW(pth,cszbs);
317     MSI_SetPropertyW(package, MPF, pth);
318
319     SHGetFolderPathW(NULL,CSIDL_PERSONAL,NULL,0,pth);
320     strcatW(pth,cszbs);
321     MSI_SetPropertyW(package, PF, pth);
322
323     SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
324     strcatW(pth,cszbs);
325     MSI_SetPropertyW(package, WF, pth);
326
327     GetTempPathW(MAX_PATH,pth);
328     MSI_SetPropertyW(package, TF, pth);
329
330
331     /* in a wine environment the user is always admin and privileged */
332     MSI_SetPropertyW(package,szAdminUser,szOne);
333     MSI_SetPropertyW(package,szPriv,szOne);
334
335     /* set the os things */
336     OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
337     GetVersionExA(&OSVersion);
338     verval = OSVersion.dwMinorVersion+OSVersion.dwMajorVersion*100;
339     sprintfW(verstr,szFormat,verval);
340     switch (OSVersion.dwPlatformId)
341     {
342         case VER_PLATFORM_WIN32_WINDOWS:    
343             MSI_SetPropertyW(package,v9x,verstr);
344             break;
345         case VER_PLATFORM_WIN32_NT:
346             MSI_SetPropertyW(package,vNT,verstr);
347             break;
348     }
349     sprintfW(verstr,szFormat,OSVersion.dwBuildNumber);
350     MSI_SetPropertyW(package,szWinBuild,verstr);
351     /* just fudge this */
352     MSI_SetPropertyW(package,szSPL,szSix);
353
354     sprintfW( msiver, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION);
355     MSI_SetPropertyW( package, szVersionMsi, msiver );
356
357     /* FIXME: these need to be set properly */
358
359     MSI_SetPropertyW(package,ProgramMenuFolder,PMFPath);
360     MSI_SetPropertyW(package,FavoritesFolder,FFPath);
361     MSI_SetPropertyW(package,FontsFolder,FoFPath);
362     MSI_SetPropertyW(package,SendToFolder,STFPath);
363     MSI_SetPropertyW(package,StartMenuFolder,SMFPath);
364     MSI_SetPropertyW(package,StartupFolder,SFPath);
365     MSI_SetPropertyW(package,TemplateFolder,TFPath);
366     MSI_SetPropertyW(package,DesktopFolder,DFPath);
367 }
368
369 UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
370 {
371     UINT rc;
372     MSIDATABASE *db = NULL;
373     MSIPACKAGE *package = NULL;
374     WCHAR uilevel[10];
375     UINT ret = ERROR_FUNCTION_FAILED;
376
377     static const WCHAR OriginalDatabase[] =
378 {'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
379     static const WCHAR Database[] =
380 {'D','A','T','A','B','A','S','E',0};
381     static const WCHAR szpi[] = {'%','i',0};
382     static const WCHAR szLevel[] = { 'U','I','L','e','v','e','l',0 };
383
384     TRACE("%s %p\n",debugstr_w(szPackage), pPackage);
385
386     if (szPackage[0] == '#')
387     {
388         INT handle = atoiW(&szPackage[1]);
389         db = msihandle2msiinfo( handle , MSIHANDLETYPE_DATABASE);
390     }
391     else
392     {
393         rc = MSI_OpenDatabaseW(szPackage, MSIDBOPEN_READONLY, &db);
394         if (rc != ERROR_SUCCESS)
395             return ERROR_FUNCTION_FAILED;
396     }
397
398     package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE),
399                                MSI_FreePackage );
400
401     if (package)
402     {
403         msiobj_addref( &db->hdr );
404
405         package->db = db;
406         package->features = NULL;
407         package->folders = NULL;
408         package->components = NULL;
409         package->files = NULL;
410         package->loaded_features = 0;
411         package->loaded_folders = 0;
412         package->loaded_components= 0;
413         package->loaded_files = 0;
414
415         /* OK, here is where we do a slew of things to the database to 
416          * prep for all that is to come as a package */
417
418         clone_properties(db);
419         set_installer_properties(package);
420         MSI_SetPropertyW(package, OriginalDatabase, szPackage);
421         MSI_SetPropertyW(package, Database, szPackage);
422         sprintfW(uilevel,szpi,gUILevel);
423         MSI_SetPropertyW(package, szLevel, uilevel);
424
425         msiobj_addref( &package->hdr );
426         *pPackage = package;
427         ret = ERROR_SUCCESS;
428     }
429
430     if( package )
431         msiobj_release( &package->hdr );
432     if( db )
433         msiobj_release( &db->hdr );
434
435     return ret;
436 }
437
438 UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
439 {
440     MSIPACKAGE *package = NULL;
441     UINT ret;
442
443     ret = MSI_OpenPackageW( szPackage, &package);
444     if( ret == ERROR_SUCCESS )
445     {
446         *phPackage = alloc_msihandle( &package->hdr );
447         msiobj_release( &package->hdr );
448     }
449     return ret;
450 }
451
452 UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
453 {
454     FIXME("%s 0x%08lx %p\n",debugstr_a(szPackage), dwOptions, phPackage);
455     return ERROR_CALL_NOT_IMPLEMENTED;
456 }
457
458 UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
459 {
460     FIXME("%s 0x%08lx %p\n",debugstr_w(szPackage), dwOptions, phPackage);
461     return ERROR_CALL_NOT_IMPLEMENTED;
462 }
463
464 MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
465 {
466     MSIPACKAGE *package;
467     MSIHANDLE handle = 0;
468
469     TRACE("(%ld)\n",hInstall);
470
471     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
472     if( package)
473     {
474         handle = alloc_msihandle( &package->db->hdr );
475         msiobj_release( &package->hdr );
476     }
477
478     return handle;
479 }
480
481 INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType,
482                                MSIRECORD *record)
483 {
484     DWORD log_type = 0;
485     LPWSTR message;
486     DWORD sz;
487     DWORD total_size = 0;
488     INT msg_field=1;
489     INT i;
490     INT rc;
491     char *msg;
492     int len;
493
494     TRACE("%x \n",eMessageType);
495     rc = 0;
496
497     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ERROR)
498         log_type |= INSTALLLOGMODE_ERROR;
499     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_WARNING)
500         log_type |= INSTALLLOGMODE_WARNING;
501     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_USER)
502         log_type |= INSTALLLOGMODE_USER;
503     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INFO)
504         log_type |= INSTALLLOGMODE_INFO;
505     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA)
506         log_type |= INSTALLLOGMODE_COMMONDATA;
507     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART)
508         log_type |= INSTALLLOGMODE_ACTIONSTART;
509     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONDATA)
510         log_type |= INSTALLLOGMODE_ACTIONDATA;
511     /* just a guess */
512     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_PROGRESS)
513         log_type |= 0x800;
514
515     message = HeapAlloc(GetProcessHeap(),0,1*sizeof (WCHAR));
516     message[0]=0;
517     msg_field = MSI_RecordGetFieldCount(record);
518     for (i = 1; i <= msg_field; i++)
519     {
520         LPWSTR tmp;
521         WCHAR number[3];
522         const static WCHAR format[] = { '%','i',':',' ',0};
523         const static WCHAR space[] = { ' ',0};
524         sz = 0;
525         MSI_RecordGetStringW(record,i,NULL,&sz);
526         sz+=4;
527         total_size+=sz*sizeof(WCHAR);
528         tmp = HeapAlloc(GetProcessHeap(),0,sz*sizeof(WCHAR));
529         message = HeapReAlloc(GetProcessHeap(),0,message,total_size*sizeof (WCHAR));
530
531         MSI_RecordGetStringW(record,i,tmp,&sz);
532
533         if (msg_field > 1)
534         {
535             sprintfW(number,format,i);
536             strcatW(message,number);
537         }
538         strcatW(message,tmp);
539         if (msg_field > 1)
540             strcatW(message,space);
541
542         HeapFree(GetProcessHeap(),0,tmp);
543     }
544
545     TRACE("(%p %lx %lx %s)\n",gUIHandler, gUIFilter, log_type,
546                              debugstr_w(message));
547
548     /* convert it to ASCII */
549     len = WideCharToMultiByte( CP_ACP, 0, message, -1,
550                                NULL, 0, NULL, NULL );
551     msg = HeapAlloc( GetProcessHeap(), 0, len );
552     WideCharToMultiByte( CP_ACP, 0, message, -1,
553                          msg, len, NULL, NULL );
554
555     if (gUIHandler && (gUIFilter & log_type))
556     {
557         rc = gUIHandler(gUIContext,eMessageType,msg);
558     }
559
560     if ((!rc) && (gszLogFile[0]) && !((eMessageType & 0xff000000) ==
561                                       INSTALLMESSAGE_PROGRESS))
562     {
563         DWORD write;
564         HANDLE log_file = CreateFileW(gszLogFile,GENERIC_WRITE, 0, NULL,
565                                   OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
566
567         if (log_file != INVALID_HANDLE_VALUE)
568         {
569             SetFilePointer(log_file,0, NULL, FILE_END);
570             WriteFile(log_file,msg,strlen(msg),&write,NULL);
571             WriteFile(log_file,"\n",1,&write,NULL);
572             CloseHandle(log_file);
573         }
574     }
575     HeapFree( GetProcessHeap(), 0, msg );
576     
577     HeapFree(GetProcessHeap(),0,message);
578     return ERROR_SUCCESS;
579 }
580
581 INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
582                               MSIHANDLE hRecord)
583 {
584     UINT ret = ERROR_INVALID_HANDLE;
585     MSIPACKAGE *package = NULL;
586     MSIRECORD *record = NULL;
587
588     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
589     if( !package )
590         goto out;
591
592     record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD );
593     if( !record )
594         goto out;
595
596     ret = MSI_ProcessMessage( package, eMessageType, record );
597
598 out:
599     if( package )
600         msiobj_release( &package->hdr );
601     if( record )
602         msiobj_release( &record->hdr );
603
604     return ret;
605 }
606
607 /* property code */
608 UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue)
609 {
610     LPWSTR szwName = NULL, szwValue = NULL;
611     UINT hr = ERROR_INSTALL_FAILURE;
612     UINT len;
613
614     if (0 == hInstall) {
615       return ERROR_INVALID_HANDLE;
616     }
617     if (NULL == szName) {
618       return ERROR_INVALID_PARAMETER;
619     }
620     if (NULL == szValue) {
621       return ERROR_INVALID_PARAMETER;
622     }
623
624     len = MultiByteToWideChar( CP_ACP, 0, szName, -1, NULL, 0 );
625     szwName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
626     if( !szwName )
627         goto end;
628     MultiByteToWideChar( CP_ACP, 0, szName, -1, szwName, len );
629
630     len = MultiByteToWideChar( CP_ACP, 0, szValue, -1, NULL, 0 );
631     szwValue = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
632     if( !szwValue)
633         goto end;
634     MultiByteToWideChar( CP_ACP, 0, szValue , -1, szwValue, len );
635
636     hr = MsiSetPropertyW( hInstall, szwName, szwValue);
637
638 end:
639     if( szwName )
640         HeapFree( GetProcessHeap(), 0, szwName );
641     if( szwValue )
642         HeapFree( GetProcessHeap(), 0, szwValue );
643
644     return hr;
645 }
646
647 UINT MSI_SetPropertyW( MSIPACKAGE *package, LPCWSTR szName, LPCWSTR szValue)
648 {
649     MSIQUERY *view;
650     MSIRECORD *row;
651     UINT rc;
652     DWORD sz = 0;
653     static const WCHAR Insert[]=
654      {'I','N','S','E','R','T',' ','i','n','t','o',' ','`','_','P','r','o','p'
655 ,'e','r','t','y','`',' ','(','`','_','P','r','o','p','e','r','t','y','`'
656 ,',','`','V','a','l','u','e','`',')',' ','V','A','L','U','E','S'
657 ,' ','(','?',')',0};
658     static const WCHAR Update[]=
659      {'U','P','D','A','T','E',' ','_','P','r','o','p','e'
660 ,'r','t','y',' ','s','e','t',' ','`','V','a','l','u','e','`',' ','='
661 ,' ','?',' ','w','h','e','r','e',' ','`','_','P','r','o','p'
662 ,'e','r','t','y','`',' ','=',' ','\'','%','s','\'',0};
663     WCHAR Query[1024];
664
665     TRACE("Setting property (%s %s)\n",debugstr_w(szName),
666           debugstr_w(szValue));
667
668     rc = MSI_GetPropertyW(package,szName,0,&sz);
669     if (rc==ERROR_MORE_DATA || rc == ERROR_SUCCESS)
670     {
671         sprintfW(Query,Update,szName);
672
673         row = MSI_CreateRecord(1);
674         MSI_RecordSetStringW(row,1,szValue);
675
676     }
677     else
678     {
679        strcpyW(Query,Insert);
680
681         row = MSI_CreateRecord(2);
682         MSI_RecordSetStringW(row,1,szName);
683         MSI_RecordSetStringW(row,2,szValue);
684     }
685
686
687     rc = MSI_DatabaseOpenViewW(package->db,Query,&view);
688     if (rc!= ERROR_SUCCESS)
689     {
690         msiobj_release(&row->hdr);
691         return rc;
692     }
693
694     rc = MSI_ViewExecute(view,row);
695
696     msiobj_release(&row->hdr);
697     MSI_ViewClose(view);
698     msiobj_release(&view->hdr);
699
700     return rc;
701 }
702
703 UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue)
704 {
705     MSIPACKAGE *package;
706     UINT ret;
707
708     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
709     if( !package)
710         return ERROR_INVALID_HANDLE;
711     ret = MSI_SetPropertyW( package, szName, szValue);
712     msiobj_release( &package->hdr );
713     return ret;
714 }
715
716 UINT WINAPI MsiGetPropertyA(MSIHANDLE hInstall, LPCSTR szName, LPSTR szValueBuf, DWORD* pchValueBuf) 
717 {
718     LPWSTR szwName = NULL, szwValueBuf = NULL;
719     UINT hr = ERROR_INSTALL_FAILURE;
720
721     if (0 == hInstall) {
722       return ERROR_INVALID_HANDLE;
723     }
724     if (NULL == szName) {
725       return ERROR_INVALID_PARAMETER;
726     }
727
728     TRACE("%lu %s %lu\n", hInstall, debugstr_a(szName), *pchValueBuf);
729
730     if (NULL != szValueBuf && NULL == pchValueBuf) {
731       return ERROR_INVALID_PARAMETER;
732     }
733     if( szName )
734     {
735         UINT len = MultiByteToWideChar( CP_ACP, 0, szName, -1, NULL, 0 );
736         szwName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
737         if( !szwName )
738             goto end;
739         MultiByteToWideChar( CP_ACP, 0, szName, -1, szwName, len );
740     } else {
741       return ERROR_INVALID_PARAMETER;
742     }
743     if( szValueBuf )
744     {
745         szwValueBuf = HeapAlloc( GetProcessHeap(), 0, (*pchValueBuf) * sizeof(WCHAR) );
746         if( !szwValueBuf )       
747             goto end;
748     }
749
750     if(  *pchValueBuf > 0 )
751     {
752         /* be sure to blank the string first */
753         szValueBuf[0]=0;      
754     }
755
756     hr = MsiGetPropertyW( hInstall, szwName, szwValueBuf, pchValueBuf );
757
758     if(  *pchValueBuf > 0 )
759     {
760         WideCharToMultiByte(CP_ACP, 0, szwValueBuf, -1, szValueBuf, *pchValueBuf, NULL, NULL);
761     }
762
763 end:
764     if( szwName )
765         HeapFree( GetProcessHeap(), 0, szwName );
766     if( szwValueBuf )
767         HeapFree( GetProcessHeap(), 0, szwValueBuf );
768
769     return hr;
770 }
771
772 UINT MSI_GetPropertyW(MSIPACKAGE *package, LPCWSTR szName, 
773                            LPWSTR szValueBuf, DWORD* pchValueBuf)
774 {
775     MSIQUERY *view;
776     MSIRECORD *row;
777     UINT rc;
778     WCHAR Query[1024]=
779     {'s','e','l','e','c','t',' ','V','a','l','u','e',' ','f','r','o','m',' '
780      ,'_','P','r','o','p','e','r','t','y',' ','w','h','e','r','e',' '
781      ,'_','P','r','o','p','e','r','t','y','=','`',0};
782
783     static const WCHAR szEnd[]={'`',0};
784
785     if (NULL == szName) {
786       return ERROR_INVALID_PARAMETER;
787     }
788
789     strcatW(Query,szName);
790     strcatW(Query,szEnd);
791     
792     rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
793     if (rc == ERROR_SUCCESS)
794     {
795         DWORD sz;
796         WCHAR value[0x100];
797     
798         /* even on unsuccessful lookup native msi blanks this string */
799         if (*pchValueBuf > 0)
800             szValueBuf[0] = 0;
801             
802         rc = MSI_ViewExecute(view, 0);
803         if (rc != ERROR_SUCCESS)
804         {
805             MSI_ViewClose(view);
806             msiobj_release(&view->hdr);
807             return rc;
808         }
809
810         rc = MSI_ViewFetch(view,&row);
811         if (rc == ERROR_SUCCESS)
812         {
813             sz=0x100;
814             rc = MSI_RecordGetStringW(row,1,value,&sz);
815             strncpyW(szValueBuf,value,min(sz+1,*pchValueBuf));
816             *pchValueBuf = sz+1;
817             msiobj_release(&row->hdr);
818         }
819         MSI_ViewClose(view);
820         msiobj_release(&view->hdr);
821     }
822
823     if (rc == ERROR_SUCCESS)
824         TRACE("returning %s for property %s\n", debugstr_w(szValueBuf),
825             debugstr_w(szName));
826     else
827     {
828         *pchValueBuf = 0;
829         TRACE("property not found\n");
830     }
831
832     return rc;
833 }
834
835   
836 UINT WINAPI MsiGetPropertyW(MSIHANDLE hInstall, LPCWSTR szName, 
837                            LPWSTR szValueBuf, DWORD* pchValueBuf)
838 {
839     MSIPACKAGE *package;
840     UINT ret;
841
842     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
843     if( !package)
844         return ERROR_INVALID_HANDLE;
845     ret = MSI_GetPropertyW(package, szName, szValueBuf, pchValueBuf );
846     msiobj_release( &package->hdr );
847     return ret;
848 }