Fixed 'break NN' command (using dbghelp.SymEnumLines).
[wine/multimedia.git] / dlls / msi / package.c
blob16a26080f9dd7a60fd477955a389e5d9482dce94
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);
44 static void MSI_FreePackage( MSIOBJECTHDR *arg)
46 MSIPACKAGE *package= (MSIPACKAGE*) arg;
48 if( package->dialog )
49 msi_dialog_destroy( package->dialog );
50 ACTION_free_package_structures(package);
52 msiobj_release( &package->db->hdr );
55 static UINT clone_properties(MSIDATABASE *db)
57 MSIQUERY * view = NULL;
58 UINT rc;
59 static const WCHAR CreateSql[] = {
60 'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','_','P','r','o',
61 'p','e','r','t','y','`',' ','(',' ','`','_','P','r','o','p','e','r','t',
62 'y','`',' ','C','H','A','R','(','5','6',')',' ','N','O','T',' ','N','U',
63 'L','L',',',' ','`','V','a','l','u','e','`',' ','C','H','A','R','(','9',
64 '8',')',' ','N','O','T',' ','N','U','L','L',' ','P','R','I','M','A','R',
65 'Y',' ','K','E','Y',' ','`','_','P','r','o','p','e','r','t','y','`',')',0};
66 static const WCHAR Query[] = {
67 'S','E','L','E','C','T',' ','*',' ',
68 'F','R','O','M',' ','`','P','r','o','p','e','r','t','y','`',0};
69 static const WCHAR Insert[] = {
70 'I','N','S','E','R','T',' ','i','n','t','o',' ',
71 '`','_','P','r','o','p','e','r','t','y','`',' ',
72 '(','`','_','P','r','o','p','e','r','t','y','`',',',
73 '`','V','a','l','u','e','`',')',' ',
74 'V','A','L','U','E','S',' ','(','?',',','?',')',0};
76 /* create the temporary properties table */
77 rc = MSI_DatabaseOpenViewW(db, CreateSql, &view);
78 if (rc != ERROR_SUCCESS)
79 return rc;
80 rc = MSI_ViewExecute(view,0);
81 MSI_ViewClose(view);
82 msiobj_release(&view->hdr);
83 if (rc != ERROR_SUCCESS)
84 return rc;
86 /* clone the existing properties */
87 rc = MSI_DatabaseOpenViewW(db, Query, &view);
88 if (rc != ERROR_SUCCESS)
89 return rc;
91 rc = MSI_ViewExecute(view, 0);
92 if (rc != ERROR_SUCCESS)
94 MSI_ViewClose(view);
95 msiobj_release(&view->hdr);
96 return rc;
98 while (1)
100 MSIRECORD * row;
101 MSIQUERY * view2;
103 rc = MSI_ViewFetch(view,&row);
104 if (rc != ERROR_SUCCESS)
105 break;
107 rc = MSI_DatabaseOpenViewW(db,Insert,&view2);
108 if (rc!= ERROR_SUCCESS)
109 continue;
110 rc = MSI_ViewExecute(view2,row);
111 MSI_ViewClose(view2);
112 msiobj_release(&view2->hdr);
114 if (rc == ERROR_SUCCESS)
115 msiobj_release(&row->hdr);
117 MSI_ViewClose(view);
118 msiobj_release(&view->hdr);
120 return rc;
124 * There are a whole slew of these we need to set
127 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/properties.asp
129 static VOID set_installer_properties(MSIPACKAGE *package)
131 WCHAR pth[MAX_PATH];
132 WCHAR *ptr;
133 OSVERSIONINFOA OSVersion;
134 MEMORYSTATUSEX msex;
135 DWORD verval;
136 WCHAR verstr[10], bufstr[20];
137 HDC dc;
139 static const WCHAR cszbs[]={'\\',0};
140 static const WCHAR CFF[] =
141 {'C','o','m','m','o','n','F','i','l','e','s','F','o','l','d','e','r',0};
142 static const WCHAR PFF[] =
143 {'P','r','o','g','r','a','m','F','i','l','e','s','F','o','l','d','e','r',0};
144 static const WCHAR CADF[] =
145 {'C','o','m','m','o','n','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
146 static const WCHAR FaF[] =
147 {'F','a','v','o','r','i','t','e','s','F','o','l','d','e','r',0};
148 static const WCHAR FoF[] =
149 {'F','o','n','t','s','F','o','l','d','e','r',0};
150 static const WCHAR SendTF[] =
151 {'S','e','n','d','T','o','F','o','l','d','e','r',0};
152 static const WCHAR SMF[] =
153 {'S','t','a','r','t','M','e','n','u','F','o','l','d','e','r',0};
154 static const WCHAR StF[] =
155 {'S','t','a','r','t','u','p','F','o','l','d','e','r',0};
156 static const WCHAR TemplF[] =
157 {'T','e','m','p','l','a','t','e','F','o','l','d','e','r',0};
158 static const WCHAR DF[] =
159 {'D','e','s','k','t','o','p','F','o','l','d','e','r',0};
160 static const WCHAR PMF[] =
161 {'P','r','o','g','r','a','m','M','e','n','u','F','o','l','d','e','r',0};
162 static const WCHAR ATF[] =
163 {'A','d','m','i','n','T','o','o','l','s','F','o','l','d','e','r',0};
164 static const WCHAR ADF[] =
165 {'A','p','p','D','a','t','a','F','o','l','d','e','r',0};
166 static const WCHAR SF[] =
167 {'S','y','s','t','e','m','F','o','l','d','e','r',0};
168 static const WCHAR SF16[] =
169 {'S','y','s','t','e','m','1','6','F','o','l','d','e','r',0};
170 static const WCHAR LADF[] =
171 {'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
172 static const WCHAR MPF[] =
173 {'M','y','P','i','c','t','u','r','e','s','F','o','l','d','e','r',0};
174 static const WCHAR PF[] =
175 {'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0};
176 static const WCHAR WF[] =
177 {'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
178 static const WCHAR WV[] =
179 {'W','i','n','d','o','w','s','V','o','l','u','m','e',0};
180 static const WCHAR TF[]=
181 {'T','e','m','p','F','o','l','d','e','r',0};
182 static const WCHAR szAdminUser[] =
183 {'A','d','m','i','n','U','s','e','r',0};
184 static const WCHAR szPriv[] =
185 {'P','r','i','v','i','l','e','g','e','d',0};
186 static const WCHAR szOne[] =
187 {'1',0};
188 static const WCHAR v9x[] = { 'V','e','r','s','i','o','n','9','X',0 };
189 static const WCHAR vNT[] = { 'V','e','r','s','i','o','n','N','T',0 };
190 static const WCHAR szFormat[] = {'%','l','i',0};
191 static const WCHAR szWinBuild[] =
192 {'W','i','n','d','o','w','s','B','u','i','l','d', 0 };
193 static const WCHAR szSPL[] =
194 {'S','e','r','v','i','c','e','P','a','c','k','L','e','v','e','l',0 };
195 static const WCHAR szSix[] = {'6',0 };
197 static const WCHAR szVersionMsi[] = { 'V','e','r','s','i','o','n','M','s','i',0 };
198 static const WCHAR szPhysicalMemory[] = { 'P','h','y','s','i','c','a','l','M','e','m','o','r','y',0 };
199 static const WCHAR szFormat2[] = {'%','l','i','.','%','l','i',0};
200 /* Screen properties */
201 static const WCHAR szScreenX[] = {'S','c','r','e','e','n','X',0};
202 static const WCHAR szScreenY[] = {'S','c','r','e','e','n','Y',0};
203 static const WCHAR szColorBits[] = {'C','o','l','o','r','B','i','t','s',0};
204 static const WCHAR szScreenFormat[] = {'%','d',0};
207 * Other things I notice set
209 SystemLanguageID
210 ComputerName
211 UserLanguageID
212 LogonUser
213 VirtualMemory
214 Intel
215 ShellAdvSupport
216 DefaultUIFont
217 VersionDatabase
218 PackagecodeChanging
219 ProductState
220 CaptionHeight
221 BorderTop
222 BorderSide
223 TextHeight
224 RedirectedDllSupport
225 Time
226 Date
227 Privileged
230 SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES_COMMON,NULL,0,pth);
231 strcatW(pth,cszbs);
232 MSI_SetPropertyW(package, CFF, pth);
234 SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES,NULL,0,pth);
235 strcatW(pth,cszbs);
236 MSI_SetPropertyW(package, PFF, pth);
238 SHGetFolderPathW(NULL,CSIDL_COMMON_APPDATA,NULL,0,pth);
239 strcatW(pth,cszbs);
240 MSI_SetPropertyW(package, CADF, pth);
242 SHGetFolderPathW(NULL,CSIDL_FAVORITES,NULL,0,pth);
243 strcatW(pth,cszbs);
244 MSI_SetPropertyW(package, FaF, pth);
246 SHGetFolderPathW(NULL,CSIDL_FONTS,NULL,0,pth);
247 strcatW(pth,cszbs);
248 MSI_SetPropertyW(package, FoF, pth);
250 SHGetFolderPathW(NULL,CSIDL_SENDTO,NULL,0,pth);
251 strcatW(pth,cszbs);
252 MSI_SetPropertyW(package, SendTF, pth);
254 SHGetFolderPathW(NULL,CSIDL_STARTMENU,NULL,0,pth);
255 strcatW(pth,cszbs);
256 MSI_SetPropertyW(package, SMF, pth);
258 SHGetFolderPathW(NULL,CSIDL_STARTUP,NULL,0,pth);
259 strcatW(pth,cszbs);
260 MSI_SetPropertyW(package, StF, pth);
262 SHGetFolderPathW(NULL,CSIDL_TEMPLATES,NULL,0,pth);
263 strcatW(pth,cszbs);
264 MSI_SetPropertyW(package, TemplF, pth);
266 SHGetFolderPathW(NULL,CSIDL_DESKTOP,NULL,0,pth);
267 strcatW(pth,cszbs);
268 MSI_SetPropertyW(package, DF, pth);
270 SHGetFolderPathW(NULL,CSIDL_PROGRAMS,NULL,0,pth);
271 strcatW(pth,cszbs);
272 MSI_SetPropertyW(package, PMF, pth);
274 SHGetFolderPathW(NULL,CSIDL_ADMINTOOLS,NULL,0,pth);
275 strcatW(pth,cszbs);
276 MSI_SetPropertyW(package, ATF, pth);
278 SHGetFolderPathW(NULL,CSIDL_APPDATA,NULL,0,pth);
279 strcatW(pth,cszbs);
280 MSI_SetPropertyW(package, ADF, pth);
282 SHGetFolderPathW(NULL,CSIDL_SYSTEM,NULL,0,pth);
283 strcatW(pth,cszbs);
284 MSI_SetPropertyW(package, SF, pth);
285 MSI_SetPropertyW(package, SF16, pth);
287 SHGetFolderPathW(NULL,CSIDL_LOCAL_APPDATA,NULL,0,pth);
288 strcatW(pth,cszbs);
289 MSI_SetPropertyW(package, LADF, pth);
291 SHGetFolderPathW(NULL,CSIDL_MYPICTURES,NULL,0,pth);
292 strcatW(pth,cszbs);
293 MSI_SetPropertyW(package, MPF, pth);
295 SHGetFolderPathW(NULL,CSIDL_PERSONAL,NULL,0,pth);
296 strcatW(pth,cszbs);
297 MSI_SetPropertyW(package, PF, pth);
299 SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
300 strcatW(pth,cszbs);
301 MSI_SetPropertyW(package, WF, pth);
303 /* Physical Memory is specified in MB. Using total amount. */
304 msex.dwLength = sizeof(msex);
305 GlobalMemoryStatusEx( &msex );
306 sprintfW( bufstr, szScreenFormat, (int)(msex.ullTotalPhys/1024/1024));
307 MSI_SetPropertyW(package, szPhysicalMemory, bufstr);
309 SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
310 ptr = strchrW(pth,'\\');
311 if (ptr)
312 *(ptr+1) = 0;
313 MSI_SetPropertyW(package, WV, pth);
315 GetTempPathW(MAX_PATH,pth);
316 MSI_SetPropertyW(package, TF, pth);
319 /* in a wine environment the user is always admin and privileged */
320 MSI_SetPropertyW(package,szAdminUser,szOne);
321 MSI_SetPropertyW(package,szPriv,szOne);
323 /* set the os things */
324 OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
325 GetVersionExA(&OSVersion);
326 verval = OSVersion.dwMinorVersion+OSVersion.dwMajorVersion*100;
327 sprintfW(verstr,szFormat,verval);
328 switch (OSVersion.dwPlatformId)
330 case VER_PLATFORM_WIN32_WINDOWS:
331 MSI_SetPropertyW(package,v9x,verstr);
332 break;
333 case VER_PLATFORM_WIN32_NT:
334 MSI_SetPropertyW(package,vNT,verstr);
335 break;
337 sprintfW(verstr,szFormat,OSVersion.dwBuildNumber);
338 MSI_SetPropertyW(package,szWinBuild,verstr);
339 /* just fudge this */
340 MSI_SetPropertyW(package,szSPL,szSix);
342 sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION);
343 MSI_SetPropertyW( package, szVersionMsi, bufstr );
345 /* Screen properties. */
346 dc = GetDC(0);
347 sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, HORZRES ) );
348 MSI_SetPropertyW( package, szScreenX, bufstr );
349 sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, VERTRES ));
350 MSI_SetPropertyW( package, szScreenY, bufstr );
351 sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, BITSPIXEL ));
352 MSI_SetPropertyW( package, szColorBits, bufstr );
353 ReleaseDC(0, dc);
356 MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db )
358 static const WCHAR szLevel[] = { 'U','I','L','e','v','e','l',0 };
359 static const WCHAR szpi[] = {'%','i',0};
360 MSIPACKAGE *package = NULL;
361 WCHAR uilevel[10];
363 TRACE("%p\n", db);
365 package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE),
366 MSI_FreePackage );
367 if( package )
369 msiobj_addref( &db->hdr );
371 package->db = db;
372 list_init( &package->components );
373 list_init( &package->features );
374 list_init( &package->files );
375 list_init( &package->tempfiles );
376 list_init( &package->folders );
377 package->ActionFormat = NULL;
378 package->LastAction = NULL;
379 package->dialog = NULL;
380 package->next_dialog = NULL;
381 list_init( &package->subscriptions );
382 list_init( &package->appids );
383 list_init( &package->classes );
384 list_init( &package->mimes );
385 list_init( &package->extensions );
386 list_init( &package->progids );
387 list_init( &package->RunningActions );
389 /* OK, here is where we do a slew of things to the database to
390 * prep for all that is to come as a package */
392 clone_properties(db);
393 set_installer_properties(package);
394 sprintfW(uilevel,szpi,gUILevel);
395 MSI_SetPropertyW(package, szLevel, uilevel);
398 return package;
402 * copy_package_to_temp [internal]
404 * copy the msi file to a temp file to prevent locking a CD
405 * with a multi disc install
407 * FIXME: I think this is wrong, and instead of copying the package,
408 * we should read all the tables to memory, then open the
409 * database to read binary streams on demand.
411 static LPCWSTR copy_package_to_temp( LPCWSTR szPackage, LPWSTR filename )
413 WCHAR path[MAX_PATH];
414 static const WCHAR szMSI[] = {'M','S','I',0};
416 GetTempPathW( MAX_PATH, path );
417 GetTempFileNameW( path, szMSI, 0, filename );
419 if( !CopyFileW( szPackage, filename, FALSE ) )
421 ERR("failed to copy package to temp path %s\n", debugstr_w(filename) );
422 return szPackage;
425 TRACE("Opening relocated package %s\n", debugstr_w( filename ));
426 return filename;
429 UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
431 MSIDATABASE *db = NULL;
432 MSIPACKAGE *package;
433 MSIHANDLE handle;
434 DWORD size;
435 static const WCHAR szProductCode[]= {'P','r','o','d','u','c','t','C','o','d','e',0};
436 UINT r;
438 TRACE("%s %p\n", debugstr_w(szPackage), pPackage);
440 if( szPackage[0] == '#' )
442 handle = atoiW(&szPackage[1]);
443 db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE );
444 if( !db )
445 return ERROR_INVALID_HANDLE;
447 else
449 WCHAR temppath[MAX_PATH];
450 LPCWSTR file = copy_package_to_temp( szPackage, temppath );
452 r = MSI_OpenDatabaseW( file, MSIDBOPEN_READONLY, &db );
454 if (file != szPackage)
455 DeleteFileW( file );
457 if( r != ERROR_SUCCESS )
458 return r;
461 package = MSI_CreatePackage( db );
462 msiobj_release( &db->hdr );
463 if( !package )
464 return ERROR_FUNCTION_FAILED;
467 * FIXME: I don't think this is right. Maybe we should be storing the
468 * name of the database in the MSIDATABASE structure and fetching this
469 * info from there, or maybe this is only relevant to cached databases.
471 if( szPackage[0] != '#' )
473 static const WCHAR OriginalDatabase[] =
474 {'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
475 static const WCHAR Database[] = {'D','A','T','A','B','A','S','E',0};
477 MSI_SetPropertyW( package, OriginalDatabase, szPackage );
478 MSI_SetPropertyW( package, Database, szPackage );
481 /* this property must exist */
482 size = 0;
483 MSI_GetPropertyW(package,szProductCode,NULL,&size);
484 size ++;
485 package->ProductCode = msi_alloc(size * sizeof(WCHAR));
486 MSI_GetPropertyW(package,szProductCode,package->ProductCode, &size);
488 *pPackage = package;
490 return ERROR_SUCCESS;
493 UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
495 MSIPACKAGE *package = NULL;
496 UINT ret;
498 TRACE("%s %08lx %p\n", debugstr_w(szPackage), dwOptions, phPackage );
500 if( dwOptions )
501 FIXME("dwOptions %08lx not supported\n", dwOptions);
503 ret = MSI_OpenPackageW( szPackage, &package );
504 if( ret == ERROR_SUCCESS )
506 *phPackage = alloc_msihandle( &package->hdr );
507 msiobj_release( &package->hdr );
510 return ret;
513 UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
515 return MsiOpenPackageExW( szPackage, 0, phPackage );
518 UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
520 LPWSTR szwPack = NULL;
521 UINT ret;
523 if( szPackage )
525 szwPack = strdupAtoW( szPackage );
526 if( !szwPack )
527 return ERROR_OUTOFMEMORY;
530 ret = MsiOpenPackageExW( szwPack, dwOptions, phPackage );
532 msi_free( szwPack );
534 return ret;
537 UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
539 return MsiOpenPackageExA( szPackage, 0, phPackage );
542 MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
544 MSIPACKAGE *package;
545 MSIHANDLE handle = 0;
547 TRACE("(%ld)\n",hInstall);
549 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
550 if( package)
552 handle = alloc_msihandle( &package->db->hdr );
553 msiobj_release( &package->hdr );
556 return handle;
559 INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType,
560 MSIRECORD *record)
562 DWORD log_type = 0;
563 LPWSTR message;
564 DWORD sz;
565 DWORD total_size = 0;
566 INT msg_field=1;
567 INT i;
568 INT rc;
569 char *msg;
570 int len;
572 TRACE("%x \n",eMessageType);
573 rc = 0;
575 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ERROR)
576 log_type |= INSTALLLOGMODE_ERROR;
577 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_WARNING)
578 log_type |= INSTALLLOGMODE_WARNING;
579 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_USER)
580 log_type |= INSTALLLOGMODE_USER;
581 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INFO)
582 log_type |= INSTALLLOGMODE_INFO;
583 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA)
584 log_type |= INSTALLLOGMODE_COMMONDATA;
585 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART)
586 log_type |= INSTALLLOGMODE_ACTIONSTART;
587 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONDATA)
588 log_type |= INSTALLLOGMODE_ACTIONDATA;
589 /* just a guess */
590 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_PROGRESS)
591 log_type |= 0x800;
593 message = msi_alloc(1*sizeof (WCHAR));
594 message[0]=0;
595 msg_field = MSI_RecordGetFieldCount(record);
596 for (i = 1; i <= msg_field; i++)
598 LPWSTR tmp;
599 WCHAR number[3];
600 static const WCHAR format[] = { '%','i',':',' ',0};
601 static const WCHAR space[] = { ' ',0};
602 sz = 0;
603 MSI_RecordGetStringW(record,i,NULL,&sz);
604 sz+=4;
605 total_size+=sz*sizeof(WCHAR);
606 tmp = msi_alloc(sz*sizeof(WCHAR));
607 message = msi_realloc(message,total_size*sizeof (WCHAR));
609 MSI_RecordGetStringW(record,i,tmp,&sz);
611 if (msg_field > 1)
613 sprintfW(number,format,i);
614 strcatW(message,number);
616 strcatW(message,tmp);
617 if (msg_field > 1)
618 strcatW(message,space);
620 msi_free(tmp);
623 TRACE("(%p %lx %lx %s)\n",gUIHandlerA, gUIFilter, log_type,
624 debugstr_w(message));
626 /* convert it to ASCII */
627 len = WideCharToMultiByte( CP_ACP, 0, message, -1,
628 NULL, 0, NULL, NULL );
629 msg = msi_alloc( len );
630 WideCharToMultiByte( CP_ACP, 0, message, -1,
631 msg, len, NULL, NULL );
633 if (gUIHandlerA && (gUIFilter & log_type))
635 rc = gUIHandlerA(gUIContext,eMessageType,msg);
638 if ((!rc) && (gszLogFile[0]) && !((eMessageType & 0xff000000) ==
639 INSTALLMESSAGE_PROGRESS))
641 DWORD write;
642 HANDLE log_file = CreateFileW(gszLogFile,GENERIC_WRITE, 0, NULL,
643 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
645 if (log_file != INVALID_HANDLE_VALUE)
647 SetFilePointer(log_file,0, NULL, FILE_END);
648 WriteFile(log_file,msg,strlen(msg),&write,NULL);
649 WriteFile(log_file,"\n",1,&write,NULL);
650 CloseHandle(log_file);
653 msi_free( msg );
655 msi_free( message);
656 return ERROR_SUCCESS;
659 INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
660 MSIHANDLE hRecord)
662 UINT ret = ERROR_INVALID_HANDLE;
663 MSIPACKAGE *package = NULL;
664 MSIRECORD *record = NULL;
666 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
667 if( !package )
668 return ERROR_INVALID_HANDLE;
670 record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD );
671 if( !record )
672 goto out;
674 ret = MSI_ProcessMessage( package, eMessageType, record );
676 out:
677 msiobj_release( &package->hdr );
678 if( record )
679 msiobj_release( &record->hdr );
681 return ret;
684 /* property code */
685 UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue )
687 LPWSTR szwName = NULL, szwValue = NULL;
688 UINT r = ERROR_OUTOFMEMORY;
690 szwName = strdupAtoW( szName );
691 if( szName && !szwName )
692 goto end;
694 szwValue = strdupAtoW( szValue );
695 if( szValue && !szwValue )
696 goto end;
698 r = MsiSetPropertyW( hInstall, szwName, szwValue);
700 end:
701 msi_free( szwName );
702 msi_free( szwValue );
704 return r;
707 UINT MSI_SetPropertyW( MSIPACKAGE *package, LPCWSTR szName, LPCWSTR szValue)
709 MSIQUERY *view;
710 MSIRECORD *row;
711 UINT rc;
712 DWORD sz = 0;
713 static const WCHAR Insert[]=
714 {'I','N','S','E','R','T',' ','i','n','t','o',' ','`','_','P','r','o','p'
715 ,'e','r','t','y','`',' ','(','`','_','P','r','o','p','e','r','t','y','`'
716 ,',','`','V','a','l','u','e','`',')',' ','V','A','L','U','E','S'
717 ,' ','(','?',',','?',')',0};
718 static const WCHAR Update[]=
719 {'U','P','D','A','T','E',' ','_','P','r','o','p','e'
720 ,'r','t','y',' ','s','e','t',' ','`','V','a','l','u','e','`',' ','='
721 ,' ','?',' ','w','h','e','r','e',' ','`','_','P','r','o','p'
722 ,'e','r','t','y','`',' ','=',' ','\'','%','s','\'',0};
723 WCHAR Query[1024];
725 TRACE("%p %s %s\n", package, debugstr_w(szName), debugstr_w(szValue));
727 if (!szName)
728 return ERROR_INVALID_PARAMETER;
730 /* this one is wierd... */
731 if (!szName[0])
732 return szValue ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS;
734 rc = MSI_GetPropertyW(package,szName,0,&sz);
735 if (rc==ERROR_MORE_DATA || rc == ERROR_SUCCESS)
737 sprintfW(Query,Update,szName);
739 row = MSI_CreateRecord(1);
740 MSI_RecordSetStringW(row,1,szValue);
743 else
745 strcpyW(Query,Insert);
747 row = MSI_CreateRecord(2);
748 MSI_RecordSetStringW(row,1,szName);
749 MSI_RecordSetStringW(row,2,szValue);
752 rc = MSI_DatabaseOpenViewW(package->db,Query,&view);
753 if (rc == ERROR_SUCCESS)
755 rc = MSI_ViewExecute(view,row);
757 MSI_ViewClose(view);
758 msiobj_release(&view->hdr);
760 msiobj_release(&row->hdr);
762 return rc;
765 UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue)
767 MSIPACKAGE *package;
768 UINT ret;
770 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
771 if( !package )
772 return ERROR_INVALID_HANDLE;
773 ret = MSI_SetPropertyW( package, szName, szValue);
774 msiobj_release( &package->hdr );
775 return ret;
778 static MSIRECORD *MSI_GetPropertyRow( MSIPACKAGE *package, LPCWSTR name )
780 static const WCHAR query[]=
781 {'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ',
782 'F','R','O','M',' ' ,'`','_','P','r','o','p','e','r','t','y','`',
783 ' ','W','H','E','R','E',' ' ,'`','_','P','r','o','p','e','r','t','y','`',
784 '=','\'','%','s','\'',0};
786 if (!name || !name[0])
787 return NULL;
789 return MSI_QueryGetRecord( package->db, query, name );
792 /* internal function, not compatible with MsiGetPropertyW */
793 UINT MSI_GetPropertyW( MSIPACKAGE *package, LPCWSTR szName,
794 LPWSTR szValueBuf, DWORD* pchValueBuf )
796 MSIRECORD *row;
797 UINT rc = ERROR_FUNCTION_FAILED;
799 row = MSI_GetPropertyRow( package, szName );
801 if (*pchValueBuf > 0)
802 szValueBuf[0] = 0;
804 if (row)
806 rc = MSI_RecordGetStringW(row,1,szValueBuf,pchValueBuf);
807 msiobj_release(&row->hdr);
810 if (rc == ERROR_SUCCESS)
811 TRACE("returning %s for property %s\n", debugstr_w(szValueBuf),
812 debugstr_w(szName));
813 else if (rc == ERROR_MORE_DATA)
814 TRACE("need %li sized buffer for %s\n", *pchValueBuf,
815 debugstr_w(szName));
816 else
818 *pchValueBuf = 0;
819 TRACE("property %s not found\n", debugstr_w(szName));
822 return rc;
825 static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name,
826 awstring *szValueBuf, DWORD* pchValueBuf )
828 static const WCHAR empty[] = {0};
829 MSIPACKAGE *package;
830 MSIRECORD *row = NULL;
831 UINT r;
832 LPCWSTR val = NULL;
834 TRACE("%lu %s %p %p\n", handle, debugstr_w(name),
835 szValueBuf->str.w, pchValueBuf );
837 if (!name)
838 return ERROR_INVALID_PARAMETER;
840 package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE );
841 if (!package)
842 return ERROR_INVALID_HANDLE;
844 row = MSI_GetPropertyRow( package, name );
845 if (row)
846 val = MSI_RecordGetString( row, 1 );
848 if (!val)
849 val = empty;
851 r = msi_strcpy_to_awstring( val, szValueBuf, pchValueBuf );
853 if (row)
854 msiobj_release( &row->hdr );
855 msiobj_release( &package->hdr );
857 return r;
860 UINT WINAPI MsiGetPropertyA( MSIHANDLE hInstall, LPCSTR szName,
861 LPSTR szValueBuf, DWORD* pchValueBuf )
863 awstring val;
864 LPWSTR name;
865 UINT r;
867 val.unicode = FALSE;
868 val.str.a = szValueBuf;
870 name = strdupAtoW( szName );
871 if (szName && !name)
872 return ERROR_OUTOFMEMORY;
874 r = MSI_GetProperty( hInstall, name, &val, pchValueBuf );
875 msi_free( name );
876 return r;
879 UINT WINAPI MsiGetPropertyW( MSIHANDLE hInstall, LPCWSTR szName,
880 LPWSTR szValueBuf, DWORD* pchValueBuf )
882 awstring val;
884 val.unicode = TRUE;
885 val.str.w = szValueBuf;
887 return MSI_GetProperty( hInstall, szName, &val, pchValueBuf );