Release 20050930.
[wine/gsoc-2012-control.git] / dlls / msi / package.c
blobb37ce4de1c69f32080ad03e6d46fad6f52e8b6aa
1 /*
2 * Implementation of the Microsoft Installer (msi.dll)
4 * Copyright 2004 Aric Stewart for CodeWeavers
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.
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.
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
21 #define NONAMELESSUNION
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 "wingdi.h"
31 #include "wine/debug.h"
32 #include "msi.h"
33 #include "msiquery.h"
34 #include "msipriv.h"
35 #include "objidl.h"
36 #include "wincrypt.h"
37 #include "winuser.h"
38 #include "shlobj.h"
39 #include "wine/unicode.h"
40 #include "objbase.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(msi);
45 * The MSVC headers define the MSIDBOPEN_* macros cast to LPCTSTR,
46 * which is a problem because LPCTSTR isn't defined when compiling wine.
47 * To work around this problem, we need to define LPCTSTR as LPCWSTR here,
48 * and make sure to only use it in W functions.
50 #define LPCTSTR LPCWSTR
52 static void MSI_FreePackage( MSIOBJECTHDR *arg)
54 MSIPACKAGE *package= (MSIPACKAGE*) arg;
56 if( package->dialog )
57 msi_dialog_destroy( package->dialog );
58 ACTION_free_package_structures(package);
60 msiobj_release( &package->db->hdr );
63 static UINT clone_properties(MSIDATABASE *db)
65 MSIQUERY * view = NULL;
66 UINT rc;
67 static const WCHAR CreateSql[] = {
68 'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','_','P','r','o',
69 'p','e','r','t','y','`',' ','(',' ','`','_','P','r','o','p','e','r','t',
70 'y','`',' ','C','H','A','R','(','5','6',')',' ','N','O','T',' ','N','U',
71 'L','L',',',' ','`','V','a','l','u','e','`',' ','C','H','A','R','(','9',
72 '8',')',' ','N','O','T',' ','N','U','L','L',' ','P','R','I','M','A','R',
73 'Y',' ','K','E','Y',' ','`','_','P','r','o','p','e','r','t','y','`',')',0};
74 static const WCHAR Query[] = {
75 'S','E','L','E','C','T',' ','*',' ',
76 'F','R','O','M',' ','`','P','r','o','p','e','r','t','y','`',0};
77 static const WCHAR Insert[] = {
78 'I','N','S','E','R','T',' ','i','n','t','o',' ',
79 '`','_','P','r','o','p','e','r','t','y','`',' ',
80 '(','`','_','P','r','o','p','e','r','t','y','`',',',
81 '`','V','a','l','u','e','`',')',' ',
82 'V','A','L','U','E','S',' ','(','?',',','?',')',0};
84 /* create the temporary properties table */
85 rc = MSI_DatabaseOpenViewW(db, CreateSql, &view);
86 if (rc != ERROR_SUCCESS)
87 return rc;
88 rc = MSI_ViewExecute(view,0);
89 MSI_ViewClose(view);
90 msiobj_release(&view->hdr);
91 if (rc != ERROR_SUCCESS)
92 return rc;
94 /* clone the existing properties */
95 rc = MSI_DatabaseOpenViewW(db, Query, &view);
96 if (rc != ERROR_SUCCESS)
97 return rc;
99 rc = MSI_ViewExecute(view, 0);
100 if (rc != ERROR_SUCCESS)
102 MSI_ViewClose(view);
103 msiobj_release(&view->hdr);
104 return rc;
106 while (1)
108 MSIRECORD * row;
109 MSIQUERY * view2;
111 rc = MSI_ViewFetch(view,&row);
112 if (rc != ERROR_SUCCESS)
113 break;
115 rc = MSI_DatabaseOpenViewW(db,Insert,&view2);
116 if (rc!= ERROR_SUCCESS)
117 continue;
118 rc = MSI_ViewExecute(view2,row);
119 MSI_ViewClose(view2);
120 msiobj_release(&view2->hdr);
122 if (rc == ERROR_SUCCESS)
123 msiobj_release(&row->hdr);
125 MSI_ViewClose(view);
126 msiobj_release(&view->hdr);
128 return rc;
132 * There are a whole slew of these we need to set
135 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/properties.asp
137 static VOID set_installer_properties(MSIPACKAGE *package)
139 WCHAR pth[MAX_PATH];
140 WCHAR *ptr;
141 OSVERSIONINFOA OSVersion;
142 MEMORYSTATUSEX msex;
143 DWORD verval;
144 WCHAR verstr[10], bufstr[20];
145 HDC dc;
147 static const WCHAR cszbs[]={'\\',0};
148 static const WCHAR CFF[] =
149 {'C','o','m','m','o','n','F','i','l','e','s','F','o','l','d','e','r',0};
150 static const WCHAR PFF[] =
151 {'P','r','o','g','r','a','m','F','i','l','e','s','F','o','l','d','e','r',0};
152 static const WCHAR CADF[] =
153 {'C','o','m','m','o','n','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
154 static const WCHAR FaF[] =
155 {'F','a','v','o','r','i','t','e','s','F','o','l','d','e','r',0};
156 static const WCHAR FoF[] =
157 {'F','o','n','t','s','F','o','l','d','e','r',0};
158 static const WCHAR SendTF[] =
159 {'S','e','n','d','T','o','F','o','l','d','e','r',0};
160 static const WCHAR SMF[] =
161 {'S','t','a','r','t','M','e','n','u','F','o','l','d','e','r',0};
162 static const WCHAR StF[] =
163 {'S','t','a','r','t','u','p','F','o','l','d','e','r',0};
164 static const WCHAR TemplF[] =
165 {'T','e','m','p','l','a','t','e','F','o','l','d','e','r',0};
166 static const WCHAR DF[] =
167 {'D','e','s','k','t','o','p','F','o','l','d','e','r',0};
168 static const WCHAR PMF[] =
169 {'P','r','o','g','r','a','m','M','e','n','u','F','o','l','d','e','r',0};
170 static const WCHAR ATF[] =
171 {'A','d','m','i','n','T','o','o','l','s','F','o','l','d','e','r',0};
172 static const WCHAR ADF[] =
173 {'A','p','p','D','a','t','a','F','o','l','d','e','r',0};
174 static const WCHAR SF[] =
175 {'S','y','s','t','e','m','F','o','l','d','e','r',0};
176 static const WCHAR SF16[] =
177 {'S','y','s','t','e','m','1','6','F','o','l','d','e','r',0};
178 static const WCHAR LADF[] =
179 {'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
180 static const WCHAR MPF[] =
181 {'M','y','P','i','c','t','u','r','e','s','F','o','l','d','e','r',0};
182 static const WCHAR PF[] =
183 {'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0};
184 static const WCHAR WF[] =
185 {'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
186 static const WCHAR WV[] =
187 {'W','i','n','d','o','w','s','V','o','l','u','m','e',0};
188 static const WCHAR TF[]=
189 {'T','e','m','p','F','o','l','d','e','r',0};
190 static const WCHAR szAdminUser[] =
191 {'A','d','m','i','n','U','s','e','r',0};
192 static const WCHAR szPriv[] =
193 {'P','r','i','v','i','l','e','g','e','d',0};
194 static const WCHAR szOne[] =
195 {'1',0};
196 static const WCHAR v9x[] = { 'V','e','r','s','i','o','n','9','X',0 };
197 static const WCHAR vNT[] = { 'V','e','r','s','i','o','n','N','T',0 };
198 static const WCHAR szFormat[] = {'%','l','i',0};
199 static const WCHAR szWinBuild[] =
200 {'W','i','n','d','o','w','s','B','u','i','l','d', 0 };
201 static const WCHAR szSPL[] =
202 {'S','e','r','v','i','c','e','P','a','c','k','L','e','v','e','l',0 };
203 static const WCHAR szSix[] = {'6',0 };
205 static const WCHAR szVersionMsi[] = { 'V','e','r','s','i','o','n','M','s','i',0 };
206 static const WCHAR szPhysicalMemory[] = { 'P','h','y','s','i','c','a','l','M','e','m','o','r','y',0 };
207 static const WCHAR szFormat2[] = {'%','l','i','.','%','l','i',0};
208 /* Screen properties */
209 static const WCHAR szScreenX[] = {'S','c','r','e','e','n','X',0};
210 static const WCHAR szScreenY[] = {'S','c','r','e','e','n','Y',0};
211 static const WCHAR szColorBits[] = {'C','o','l','o','r','B','i','t','s',0};
212 static const WCHAR szScreenFormat[] = {'%','d',0};
215 * Other things I notice set
217 SystemLanguageID
218 ComputerName
219 UserLanguageID
220 LogonUser
221 VirtualMemory
222 Intel
223 ShellAdvSupport
224 DefaultUIFont
225 VersionDatabase
226 PackagecodeChanging
227 ProductState
228 CaptionHeight
229 BorderTop
230 BorderSide
231 TextHeight
232 RedirectedDllSupport
233 Time
234 Date
235 Privileged
238 SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES_COMMON,NULL,0,pth);
239 strcatW(pth,cszbs);
240 MSI_SetPropertyW(package, CFF, pth);
242 SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES,NULL,0,pth);
243 strcatW(pth,cszbs);
244 MSI_SetPropertyW(package, PFF, pth);
246 SHGetFolderPathW(NULL,CSIDL_COMMON_APPDATA,NULL,0,pth);
247 strcatW(pth,cszbs);
248 MSI_SetPropertyW(package, CADF, pth);
250 SHGetFolderPathW(NULL,CSIDL_FAVORITES,NULL,0,pth);
251 strcatW(pth,cszbs);
252 MSI_SetPropertyW(package, FaF, pth);
254 SHGetFolderPathW(NULL,CSIDL_FONTS,NULL,0,pth);
255 strcatW(pth,cszbs);
256 MSI_SetPropertyW(package, FoF, pth);
258 SHGetFolderPathW(NULL,CSIDL_SENDTO,NULL,0,pth);
259 strcatW(pth,cszbs);
260 MSI_SetPropertyW(package, SendTF, pth);
262 SHGetFolderPathW(NULL,CSIDL_STARTMENU,NULL,0,pth);
263 strcatW(pth,cszbs);
264 MSI_SetPropertyW(package, SMF, pth);
266 SHGetFolderPathW(NULL,CSIDL_STARTUP,NULL,0,pth);
267 strcatW(pth,cszbs);
268 MSI_SetPropertyW(package, StF, pth);
270 SHGetFolderPathW(NULL,CSIDL_TEMPLATES,NULL,0,pth);
271 strcatW(pth,cszbs);
272 MSI_SetPropertyW(package, TemplF, pth);
274 SHGetFolderPathW(NULL,CSIDL_DESKTOP,NULL,0,pth);
275 strcatW(pth,cszbs);
276 MSI_SetPropertyW(package, DF, pth);
278 SHGetFolderPathW(NULL,CSIDL_PROGRAMS,NULL,0,pth);
279 strcatW(pth,cszbs);
280 MSI_SetPropertyW(package, PMF, pth);
282 SHGetFolderPathW(NULL,CSIDL_ADMINTOOLS,NULL,0,pth);
283 strcatW(pth,cszbs);
284 MSI_SetPropertyW(package, ATF, pth);
286 SHGetFolderPathW(NULL,CSIDL_APPDATA,NULL,0,pth);
287 strcatW(pth,cszbs);
288 MSI_SetPropertyW(package, ADF, pth);
290 SHGetFolderPathW(NULL,CSIDL_SYSTEM,NULL,0,pth);
291 strcatW(pth,cszbs);
292 MSI_SetPropertyW(package, SF, pth);
293 MSI_SetPropertyW(package, SF16, pth);
295 SHGetFolderPathW(NULL,CSIDL_LOCAL_APPDATA,NULL,0,pth);
296 strcatW(pth,cszbs);
297 MSI_SetPropertyW(package, LADF, pth);
299 SHGetFolderPathW(NULL,CSIDL_MYPICTURES,NULL,0,pth);
300 strcatW(pth,cszbs);
301 MSI_SetPropertyW(package, MPF, pth);
303 SHGetFolderPathW(NULL,CSIDL_PERSONAL,NULL,0,pth);
304 strcatW(pth,cszbs);
305 MSI_SetPropertyW(package, PF, pth);
307 SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
308 strcatW(pth,cszbs);
309 MSI_SetPropertyW(package, WF, pth);
311 /* Physical Memory is specified in MB. Using total amount. */
312 msex.dwLength = sizeof(msex);
313 GlobalMemoryStatusEx( &msex );
314 sprintfW( bufstr, szScreenFormat, (int)(msex.ullTotalPhys/1024/1024));
315 MSI_SetPropertyW(package, szPhysicalMemory, bufstr);
317 SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
318 ptr = strchrW(pth,'\\');
319 if (ptr)
320 *(ptr+1) = 0;
321 MSI_SetPropertyW(package, WV, pth);
323 GetTempPathW(MAX_PATH,pth);
324 MSI_SetPropertyW(package, TF, pth);
327 /* in a wine environment the user is always admin and privileged */
328 MSI_SetPropertyW(package,szAdminUser,szOne);
329 MSI_SetPropertyW(package,szPriv,szOne);
331 /* set the os things */
332 OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
333 GetVersionExA(&OSVersion);
334 verval = OSVersion.dwMinorVersion+OSVersion.dwMajorVersion*100;
335 sprintfW(verstr,szFormat,verval);
336 switch (OSVersion.dwPlatformId)
338 case VER_PLATFORM_WIN32_WINDOWS:
339 MSI_SetPropertyW(package,v9x,verstr);
340 break;
341 case VER_PLATFORM_WIN32_NT:
342 MSI_SetPropertyW(package,vNT,verstr);
343 break;
345 sprintfW(verstr,szFormat,OSVersion.dwBuildNumber);
346 MSI_SetPropertyW(package,szWinBuild,verstr);
347 /* just fudge this */
348 MSI_SetPropertyW(package,szSPL,szSix);
350 sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION);
351 MSI_SetPropertyW( package, szVersionMsi, bufstr );
353 /* Screen properties. */
354 dc = GetDC(0);
355 sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, HORZRES ) );
356 MSI_SetPropertyW( package, szScreenX, bufstr );
357 sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, VERTRES ));
358 MSI_SetPropertyW( package, szScreenY, bufstr );
359 sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, BITSPIXEL ));
360 MSI_SetPropertyW( package, szColorBits, bufstr );
361 ReleaseDC(0, dc);
364 MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db )
366 static const WCHAR szLevel[] = { 'U','I','L','e','v','e','l',0 };
367 static const WCHAR szpi[] = {'%','i',0};
368 MSIPACKAGE *package = NULL;
369 WCHAR uilevel[10];
371 TRACE("%p\n", db);
373 package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE),
374 MSI_FreePackage );
375 if( package )
377 msiobj_addref( &db->hdr );
379 package->db = db;
380 list_init( &package->components );
381 list_init( &package->features );
382 list_init( &package->files );
383 list_init( &package->tempfiles );
384 list_init( &package->folders );
385 package->ActionFormat = NULL;
386 package->LastAction = NULL;
387 package->dialog = NULL;
388 package->next_dialog = NULL;
389 list_init( &package->subscriptions );
390 list_init( &package->appids );
391 list_init( &package->classes );
392 list_init( &package->mimes );
393 list_init( &package->extensions );
394 list_init( &package->progids );
395 list_init( &package->RunningActions );
397 /* OK, here is where we do a slew of things to the database to
398 * prep for all that is to come as a package */
400 clone_properties(db);
401 set_installer_properties(package);
402 sprintfW(uilevel,szpi,gUILevel);
403 MSI_SetPropertyW(package, szLevel, uilevel);
406 return package;
410 * copy_package_to_temp [internal]
412 * copy the msi file to a temp file to prevent locking a CD
413 * with a multi disc install
415 * FIXME: I think this is wrong, and instead of copying the package,
416 * we should read all the tables to memory, then open the
417 * database to read binary streams on demand.
419 static LPCWSTR copy_package_to_temp( LPCWSTR szPackage, LPWSTR filename )
421 WCHAR path[MAX_PATH];
422 static const WCHAR szMSI[] = {'M','S','I',0};
424 GetTempPathW( MAX_PATH, path );
425 GetTempFileNameW( path, szMSI, 0, filename );
427 if( !CopyFileW( szPackage, filename, FALSE ) )
429 ERR("failed to copy package to temp path %s\n", debugstr_w(filename) );
430 return szPackage;
433 TRACE("Opening relocated package %s\n", debugstr_w( filename ));
434 return filename;
437 UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
439 MSIDATABASE *db = NULL;
440 MSIPACKAGE *package;
441 MSIHANDLE handle;
442 DWORD size;
443 static const WCHAR szProductCode[]= {'P','r','o','d','u','c','t','C','o','d','e',0};
444 UINT r;
446 TRACE("%s %p\n", debugstr_w(szPackage), pPackage);
448 if( szPackage[0] == '#' )
450 handle = atoiW(&szPackage[1]);
451 db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE );
452 if( !db )
453 return ERROR_INVALID_HANDLE;
455 else
457 WCHAR temppath[MAX_PATH];
458 LPCWSTR file = copy_package_to_temp( szPackage, temppath );
460 r = MSI_OpenDatabaseW( file, MSIDBOPEN_READONLY, &db );
462 if (file != szPackage)
463 DeleteFileW( file );
465 if( r != ERROR_SUCCESS )
466 return r;
469 package = MSI_CreatePackage( db );
470 msiobj_release( &db->hdr );
471 if( !package )
472 return ERROR_FUNCTION_FAILED;
475 * FIXME: I don't think this is right. Maybe we should be storing the
476 * name of the database in the MSIDATABASE structure and fetching this
477 * info from there, or maybe this is only relevant to cached databases.
479 if( szPackage[0] != '#' )
481 static const WCHAR OriginalDatabase[] =
482 {'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
483 static const WCHAR Database[] = {'D','A','T','A','B','A','S','E',0};
485 MSI_SetPropertyW( package, OriginalDatabase, szPackage );
486 MSI_SetPropertyW( package, Database, szPackage );
489 /* this property must exist */
490 size = 0;
491 MSI_GetPropertyW(package,szProductCode,NULL,&size);
492 size ++;
493 package->ProductCode = msi_alloc(size * sizeof(WCHAR));
494 MSI_GetPropertyW(package,szProductCode,package->ProductCode, &size);
496 *pPackage = package;
498 return ERROR_SUCCESS;
501 UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
503 MSIPACKAGE *package = NULL;
504 UINT ret;
506 TRACE("%s %08lx %p\n", debugstr_w(szPackage), dwOptions, phPackage );
508 if( dwOptions )
509 FIXME("dwOptions %08lx not supported\n", dwOptions);
511 ret = MSI_OpenPackageW( szPackage, &package );
512 if( ret == ERROR_SUCCESS )
514 *phPackage = alloc_msihandle( &package->hdr );
515 msiobj_release( &package->hdr );
518 return ret;
521 UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
523 return MsiOpenPackageExW( szPackage, 0, phPackage );
526 UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
528 LPWSTR szwPack = NULL;
529 UINT ret;
531 if( szPackage )
533 szwPack = strdupAtoW( szPackage );
534 if( !szwPack )
535 return ERROR_OUTOFMEMORY;
538 ret = MsiOpenPackageExW( szwPack, dwOptions, phPackage );
540 msi_free( szwPack );
542 return ret;
545 UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
547 return MsiOpenPackageExA( szPackage, 0, phPackage );
550 MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
552 MSIPACKAGE *package;
553 MSIHANDLE handle = 0;
555 TRACE("(%ld)\n",hInstall);
557 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
558 if( package)
560 handle = alloc_msihandle( &package->db->hdr );
561 msiobj_release( &package->hdr );
564 return handle;
567 INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType,
568 MSIRECORD *record)
570 DWORD log_type = 0;
571 LPWSTR message;
572 DWORD sz;
573 DWORD total_size = 0;
574 INT msg_field=1;
575 INT i;
576 INT rc;
577 char *msg;
578 int len;
580 TRACE("%x \n",eMessageType);
581 rc = 0;
583 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ERROR)
584 log_type |= INSTALLLOGMODE_ERROR;
585 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_WARNING)
586 log_type |= INSTALLLOGMODE_WARNING;
587 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_USER)
588 log_type |= INSTALLLOGMODE_USER;
589 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INFO)
590 log_type |= INSTALLLOGMODE_INFO;
591 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA)
592 log_type |= INSTALLLOGMODE_COMMONDATA;
593 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART)
594 log_type |= INSTALLLOGMODE_ACTIONSTART;
595 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONDATA)
596 log_type |= INSTALLLOGMODE_ACTIONDATA;
597 /* just a guess */
598 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_PROGRESS)
599 log_type |= 0x800;
601 message = msi_alloc(1*sizeof (WCHAR));
602 message[0]=0;
603 msg_field = MSI_RecordGetFieldCount(record);
604 for (i = 1; i <= msg_field; i++)
606 LPWSTR tmp;
607 WCHAR number[3];
608 const static WCHAR format[] = { '%','i',':',' ',0};
609 const static WCHAR space[] = { ' ',0};
610 sz = 0;
611 MSI_RecordGetStringW(record,i,NULL,&sz);
612 sz+=4;
613 total_size+=sz*sizeof(WCHAR);
614 tmp = msi_alloc(sz*sizeof(WCHAR));
615 message = msi_realloc(message,total_size*sizeof (WCHAR));
617 MSI_RecordGetStringW(record,i,tmp,&sz);
619 if (msg_field > 1)
621 sprintfW(number,format,i);
622 strcatW(message,number);
624 strcatW(message,tmp);
625 if (msg_field > 1)
626 strcatW(message,space);
628 msi_free(tmp);
631 TRACE("(%p %lx %lx %s)\n",gUIHandlerA, gUIFilter, log_type,
632 debugstr_w(message));
634 /* convert it to ASCII */
635 len = WideCharToMultiByte( CP_ACP, 0, message, -1,
636 NULL, 0, NULL, NULL );
637 msg = msi_alloc( len );
638 WideCharToMultiByte( CP_ACP, 0, message, -1,
639 msg, len, NULL, NULL );
641 if (gUIHandlerA && (gUIFilter & log_type))
643 rc = gUIHandlerA(gUIContext,eMessageType,msg);
646 if ((!rc) && (gszLogFile[0]) && !((eMessageType & 0xff000000) ==
647 INSTALLMESSAGE_PROGRESS))
649 DWORD write;
650 HANDLE log_file = CreateFileW(gszLogFile,GENERIC_WRITE, 0, NULL,
651 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
653 if (log_file != INVALID_HANDLE_VALUE)
655 SetFilePointer(log_file,0, NULL, FILE_END);
656 WriteFile(log_file,msg,strlen(msg),&write,NULL);
657 WriteFile(log_file,"\n",1,&write,NULL);
658 CloseHandle(log_file);
661 msi_free( msg );
663 msi_free( message);
664 return ERROR_SUCCESS;
667 INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
668 MSIHANDLE hRecord)
670 UINT ret = ERROR_INVALID_HANDLE;
671 MSIPACKAGE *package = NULL;
672 MSIRECORD *record = NULL;
674 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
675 if( !package )
676 return ERROR_INVALID_HANDLE;
678 record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD );
679 if( !record )
680 goto out;
682 ret = MSI_ProcessMessage( package, eMessageType, record );
684 out:
685 msiobj_release( &package->hdr );
686 if( record )
687 msiobj_release( &record->hdr );
689 return ret;
692 /* property code */
693 UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue)
695 LPWSTR szwName = NULL, szwValue = NULL;
696 UINT hr = ERROR_INSTALL_FAILURE;
698 if( szName )
700 szwName = strdupAtoW( szName );
701 if( !szwName )
702 goto end;
705 if( szValue )
707 szwValue = strdupAtoW( szValue );
708 if( !szwValue)
709 goto end;
712 hr = MsiSetPropertyW( hInstall, szwName, szwValue);
714 end:
715 msi_free( szwName );
716 msi_free( szwValue );
718 return hr;
721 UINT MSI_SetPropertyW( MSIPACKAGE *package, LPCWSTR szName, LPCWSTR szValue)
723 MSIQUERY *view;
724 MSIRECORD *row;
725 UINT rc;
726 DWORD sz = 0;
727 static const WCHAR Insert[]=
728 {'I','N','S','E','R','T',' ','i','n','t','o',' ','`','_','P','r','o','p'
729 ,'e','r','t','y','`',' ','(','`','_','P','r','o','p','e','r','t','y','`'
730 ,',','`','V','a','l','u','e','`',')',' ','V','A','L','U','E','S'
731 ,' ','(','?',',','?',')',0};
732 static const WCHAR Update[]=
733 {'U','P','D','A','T','E',' ','_','P','r','o','p','e'
734 ,'r','t','y',' ','s','e','t',' ','`','V','a','l','u','e','`',' ','='
735 ,' ','?',' ','w','h','e','r','e',' ','`','_','P','r','o','p'
736 ,'e','r','t','y','`',' ','=',' ','\'','%','s','\'',0};
737 WCHAR Query[1024];
739 TRACE("Setting property (%s %s)\n",debugstr_w(szName),
740 debugstr_w(szValue));
742 rc = MSI_GetPropertyW(package,szName,0,&sz);
743 if (rc==ERROR_MORE_DATA || rc == ERROR_SUCCESS)
745 sprintfW(Query,Update,szName);
747 row = MSI_CreateRecord(1);
748 MSI_RecordSetStringW(row,1,szValue);
751 else
753 strcpyW(Query,Insert);
755 row = MSI_CreateRecord(2);
756 MSI_RecordSetStringW(row,1,szName);
757 MSI_RecordSetStringW(row,2,szValue);
760 rc = MSI_DatabaseOpenViewW(package->db,Query,&view);
761 if (rc == ERROR_SUCCESS)
763 rc = MSI_ViewExecute(view,row);
765 MSI_ViewClose(view);
766 msiobj_release(&view->hdr);
768 msiobj_release(&row->hdr);
770 return rc;
773 UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue)
775 MSIPACKAGE *package;
776 UINT ret;
778 if (NULL == szName)
779 return ERROR_INVALID_PARAMETER;
780 if (NULL == szValue)
781 return ERROR_INVALID_PARAMETER;
783 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
784 if( !package )
785 return ERROR_INVALID_HANDLE;
786 ret = MSI_SetPropertyW( package, szName, szValue);
787 msiobj_release( &package->hdr );
788 return ret;
791 static UINT MSI_GetPropertyRow(MSIPACKAGE *package, LPCWSTR szName, MSIRECORD **row)
793 MSIQUERY *view;
794 UINT rc, sz;
795 static const WCHAR select[]=
796 {'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ',
797 'F','R','O','M',' ' ,'`','_','P','r','o','p','e','r','t','y','`',
798 ' ','W','H','E','R','E',' ' ,'`','_','P','r','o','p','e','r','t','y','`',
799 '=','\'','%','s','\'',0};
800 LPWSTR query;
802 if (!szName)
803 return ERROR_INVALID_PARAMETER;
805 sz = sizeof select + strlenW(szName)*sizeof(WCHAR);
806 query = msi_alloc( sz);
807 sprintfW(query,select,szName);
809 rc = MSI_DatabaseOpenViewW(package->db, query, &view);
810 msi_free(query);
811 if (rc == ERROR_SUCCESS)
813 rc = MSI_ViewExecute(view, 0);
814 if (rc == ERROR_SUCCESS)
815 rc = MSI_ViewFetch(view,row);
817 MSI_ViewClose(view);
818 msiobj_release(&view->hdr);
821 return rc;
824 UINT MSI_GetPropertyW(MSIPACKAGE *package, LPCWSTR szName,
825 LPWSTR szValueBuf, DWORD* pchValueBuf)
827 MSIRECORD *row;
828 UINT rc;
830 rc = MSI_GetPropertyRow(package, szName, &row);
832 if (*pchValueBuf > 0)
833 szValueBuf[0] = 0;
835 if (rc == ERROR_SUCCESS)
837 rc = MSI_RecordGetStringW(row,1,szValueBuf,pchValueBuf);
838 msiobj_release(&row->hdr);
841 if (rc == ERROR_SUCCESS)
842 TRACE("returning %s for property %s\n", debugstr_w(szValueBuf),
843 debugstr_w(szName));
844 else if (rc == ERROR_MORE_DATA)
845 TRACE("need %li sized buffer for %s\n", *pchValueBuf,
846 debugstr_w(szName));
847 else
849 *pchValueBuf = 0;
850 TRACE("property %s not found\n", debugstr_w(szName));
853 return rc;
856 UINT MSI_GetPropertyA(MSIPACKAGE *package, LPCSTR szName,
857 LPSTR szValueBuf, DWORD* pchValueBuf)
859 MSIRECORD *row;
860 UINT rc;
861 LPWSTR szwName = NULL;
863 if (*pchValueBuf > 0)
864 szValueBuf[0] = 0;
866 if( szName )
868 szwName = strdupAtoW( szName );
869 if (!szwName)
870 return ERROR_NOT_ENOUGH_MEMORY;
873 rc = MSI_GetPropertyRow(package, szwName, &row);
874 if (rc == ERROR_SUCCESS)
876 rc = MSI_RecordGetStringA(row,1,szValueBuf,pchValueBuf);
877 msiobj_release(&row->hdr);
880 if (rc == ERROR_SUCCESS)
881 TRACE("returning %s for property %s\n", debugstr_a(szValueBuf),
882 debugstr_a(szName));
883 else if (rc == ERROR_MORE_DATA)
884 TRACE("need %ld sized buffer for %s\n", *pchValueBuf,
885 debugstr_a(szName));
886 else
888 *pchValueBuf = 0;
889 TRACE("property not found\n");
891 msi_free( szwName );
893 return rc;
896 UINT WINAPI MsiGetPropertyA(MSIHANDLE hInstall, LPCSTR szName, LPSTR szValueBuf, DWORD* pchValueBuf)
898 MSIPACKAGE *package;
899 UINT ret;
901 TRACE("%lu %s %p\n", hInstall, debugstr_a(szName), pchValueBuf);
903 if (0 == hInstall)
904 return ERROR_INVALID_HANDLE;
905 if (NULL == szName)
906 return ERROR_INVALID_PARAMETER;
907 if (NULL != szValueBuf && NULL == pchValueBuf)
908 return ERROR_INVALID_PARAMETER;
910 /* This was tested against native msi */
911 if (NULL == szValueBuf && NULL != pchValueBuf)
912 *pchValueBuf = 0;
914 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
915 if (!package)
916 return ERROR_INVALID_HANDLE;
917 ret = MSI_GetPropertyA(package, szName, szValueBuf, pchValueBuf );
918 msiobj_release( &package->hdr );
920 /* MsiGetProperty does not return error codes on missing properties */
921 if (ret != ERROR_MORE_DATA)
922 ret = ERROR_SUCCESS;
924 return ret;
928 UINT WINAPI MsiGetPropertyW(MSIHANDLE hInstall, LPCWSTR szName,
929 LPWSTR szValueBuf, DWORD* pchValueBuf)
931 MSIPACKAGE *package;
932 UINT ret;
934 TRACE("%lu %s %p\n", hInstall, debugstr_w(szName), pchValueBuf);
936 if (0 == hInstall)
937 return ERROR_INVALID_HANDLE;
938 if (NULL == szName)
939 return ERROR_INVALID_PARAMETER;
940 if (NULL != szValueBuf && NULL == pchValueBuf)
941 return ERROR_INVALID_PARAMETER;
943 /* This was tested against native msi */
944 if (NULL == szValueBuf && NULL != pchValueBuf)
945 *pchValueBuf = 0;
947 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
948 if (!package)
949 return ERROR_INVALID_HANDLE;
950 ret = MSI_GetPropertyW(package, szName, szValueBuf, pchValueBuf );
951 msiobj_release( &package->hdr );
953 /* MsiGetProperty does not return error codes on missing properties */
954 if (ret != ERROR_MORE_DATA)
955 ret = ERROR_SUCCESS;
957 return ret;