Added memory allocation inline functions (part 2).
[wine/wine-kai.git] / dlls / msi / package.c
blob069aa5bd434783a4dd117ad575b4af7285f7c8d4
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;
409 UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
411 MSIDATABASE *db = NULL;
412 MSIPACKAGE *package;
413 MSIHANDLE handle;
414 DWORD size;
415 static const WCHAR szProductCode[]= {'P','r','o','d','u','c','t','C','o','d','e',0};
417 TRACE("%s %p\n", debugstr_w(szPackage), pPackage);
419 if( szPackage[0] == '#' )
421 handle = atoiW(&szPackage[1]);
422 db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE );
423 if( !db )
424 return ERROR_INVALID_HANDLE;
426 else
428 UINT r = MSI_OpenDatabaseW(szPackage, MSIDBOPEN_READONLY, &db);
429 if( r != ERROR_SUCCESS )
430 return r;
433 package = MSI_CreatePackage( db );
434 msiobj_release( &db->hdr );
435 if( !package )
436 return ERROR_FUNCTION_FAILED;
439 * FIXME: I don't think this is right. Maybe we should be storing the
440 * name of the database in the MSIDATABASE structure and fetching this
441 * info from there, or maybe this is only relevant to cached databases.
443 if( szPackage[0] != '#' )
445 static const WCHAR OriginalDatabase[] =
446 {'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
447 static const WCHAR Database[] = {'D','A','T','A','B','A','S','E',0};
449 MSI_SetPropertyW( package, OriginalDatabase, szPackage );
450 MSI_SetPropertyW( package, Database, szPackage );
453 /* this property must exist */
454 size = 0;
455 MSI_GetPropertyW(package,szProductCode,NULL,&size);
456 size ++;
457 package->ProductCode = msi_alloc(size * sizeof(WCHAR));
458 MSI_GetPropertyW(package,szProductCode,package->ProductCode, &size);
460 *pPackage = package;
462 return ERROR_SUCCESS;
465 UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
467 MSIPACKAGE *package = NULL;
468 UINT ret;
469 WCHAR path[MAX_PATH];
470 WCHAR filename[MAX_PATH];
471 static const WCHAR szMSI[] = {'M','S','I',0};
473 TRACE("%s %08lx %p\n",debugstr_w(szPackage), dwOptions, phPackage);
475 /* copy the msi file to a temp file to pervent locking a CD
476 * with a multi disc install
478 if( szPackage[0] == '#' )
479 strcpyW(filename,szPackage);
480 else
482 GetTempPathW(MAX_PATH, path);
483 GetTempFileNameW(path, szMSI, 0, filename);
485 CopyFileW(szPackage, filename, FALSE);
487 TRACE("Opening relocated package %s\n",debugstr_w(filename));
490 if( dwOptions )
491 FIXME("dwOptions %08lx not supported\n", dwOptions);
493 ret = MSI_OpenPackageW( filename, &package);
494 if( ret == ERROR_SUCCESS )
496 *phPackage = alloc_msihandle( &package->hdr );
497 msiobj_release( &package->hdr );
500 if( szPackage[0] != '#' )
501 DeleteFileW(filename);
503 return ret;
506 UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
508 return MsiOpenPackageExW( szPackage, 0, phPackage );
511 UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
513 LPWSTR szwPack = NULL;
514 UINT ret;
516 if( szPackage )
518 szwPack = strdupAtoW( szPackage );
519 if( !szwPack )
520 return ERROR_OUTOFMEMORY;
523 ret = MsiOpenPackageExW( szwPack, dwOptions, phPackage );
525 msi_free( szwPack );
527 return ret;
530 UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
532 return MsiOpenPackageExA( szPackage, 0, phPackage );
535 MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
537 MSIPACKAGE *package;
538 MSIHANDLE handle = 0;
540 TRACE("(%ld)\n",hInstall);
542 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
543 if( package)
545 handle = alloc_msihandle( &package->db->hdr );
546 msiobj_release( &package->hdr );
549 return handle;
552 INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType,
553 MSIRECORD *record)
555 DWORD log_type = 0;
556 LPWSTR message;
557 DWORD sz;
558 DWORD total_size = 0;
559 INT msg_field=1;
560 INT i;
561 INT rc;
562 char *msg;
563 int len;
565 TRACE("%x \n",eMessageType);
566 rc = 0;
568 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ERROR)
569 log_type |= INSTALLLOGMODE_ERROR;
570 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_WARNING)
571 log_type |= INSTALLLOGMODE_WARNING;
572 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_USER)
573 log_type |= INSTALLLOGMODE_USER;
574 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INFO)
575 log_type |= INSTALLLOGMODE_INFO;
576 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA)
577 log_type |= INSTALLLOGMODE_COMMONDATA;
578 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART)
579 log_type |= INSTALLLOGMODE_ACTIONSTART;
580 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONDATA)
581 log_type |= INSTALLLOGMODE_ACTIONDATA;
582 /* just a guess */
583 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_PROGRESS)
584 log_type |= 0x800;
586 message = msi_alloc(1*sizeof (WCHAR));
587 message[0]=0;
588 msg_field = MSI_RecordGetFieldCount(record);
589 for (i = 1; i <= msg_field; i++)
591 LPWSTR tmp;
592 WCHAR number[3];
593 const static WCHAR format[] = { '%','i',':',' ',0};
594 const static WCHAR space[] = { ' ',0};
595 sz = 0;
596 MSI_RecordGetStringW(record,i,NULL,&sz);
597 sz+=4;
598 total_size+=sz*sizeof(WCHAR);
599 tmp = msi_alloc(sz*sizeof(WCHAR));
600 message = msi_realloc(message,total_size*sizeof (WCHAR));
602 MSI_RecordGetStringW(record,i,tmp,&sz);
604 if (msg_field > 1)
606 sprintfW(number,format,i);
607 strcatW(message,number);
609 strcatW(message,tmp);
610 if (msg_field > 1)
611 strcatW(message,space);
613 msi_free(tmp);
616 TRACE("(%p %lx %lx %s)\n",gUIHandlerA, gUIFilter, log_type,
617 debugstr_w(message));
619 /* convert it to ASCII */
620 len = WideCharToMultiByte( CP_ACP, 0, message, -1,
621 NULL, 0, NULL, NULL );
622 msg = msi_alloc( len );
623 WideCharToMultiByte( CP_ACP, 0, message, -1,
624 msg, len, NULL, NULL );
626 if (gUIHandlerA && (gUIFilter & log_type))
628 rc = gUIHandlerA(gUIContext,eMessageType,msg);
631 if ((!rc) && (gszLogFile[0]) && !((eMessageType & 0xff000000) ==
632 INSTALLMESSAGE_PROGRESS))
634 DWORD write;
635 HANDLE log_file = CreateFileW(gszLogFile,GENERIC_WRITE, 0, NULL,
636 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
638 if (log_file != INVALID_HANDLE_VALUE)
640 SetFilePointer(log_file,0, NULL, FILE_END);
641 WriteFile(log_file,msg,strlen(msg),&write,NULL);
642 WriteFile(log_file,"\n",1,&write,NULL);
643 CloseHandle(log_file);
646 msi_free( msg );
648 msi_free( message);
649 return ERROR_SUCCESS;
652 INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
653 MSIHANDLE hRecord)
655 UINT ret = ERROR_INVALID_HANDLE;
656 MSIPACKAGE *package = NULL;
657 MSIRECORD *record = NULL;
659 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
660 if( !package )
661 return ERROR_INVALID_HANDLE;
663 record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD );
664 if( !record )
665 goto out;
667 ret = MSI_ProcessMessage( package, eMessageType, record );
669 out:
670 msiobj_release( &package->hdr );
671 if( record )
672 msiobj_release( &record->hdr );
674 return ret;
677 /* property code */
678 UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue)
680 LPWSTR szwName = NULL, szwValue = NULL;
681 UINT hr = ERROR_INSTALL_FAILURE;
683 if( szName )
685 szwName = strdupAtoW( szName );
686 if( !szwName )
687 goto end;
690 if( szValue )
692 szwValue = strdupAtoW( szValue );
693 if( !szwValue)
694 goto end;
697 hr = MsiSetPropertyW( hInstall, szwName, szwValue);
699 end:
700 msi_free( szwName );
701 msi_free( szwValue );
703 return hr;
706 UINT MSI_SetPropertyW( MSIPACKAGE *package, LPCWSTR szName, LPCWSTR szValue)
708 MSIQUERY *view;
709 MSIRECORD *row;
710 UINT rc;
711 DWORD sz = 0;
712 static const WCHAR Insert[]=
713 {'I','N','S','E','R','T',' ','i','n','t','o',' ','`','_','P','r','o','p'
714 ,'e','r','t','y','`',' ','(','`','_','P','r','o','p','e','r','t','y','`'
715 ,',','`','V','a','l','u','e','`',')',' ','V','A','L','U','E','S'
716 ,' ','(','?',',','?',')',0};
717 static const WCHAR Update[]=
718 {'U','P','D','A','T','E',' ','_','P','r','o','p','e'
719 ,'r','t','y',' ','s','e','t',' ','`','V','a','l','u','e','`',' ','='
720 ,' ','?',' ','w','h','e','r','e',' ','`','_','P','r','o','p'
721 ,'e','r','t','y','`',' ','=',' ','\'','%','s','\'',0};
722 WCHAR Query[1024];
724 TRACE("Setting property (%s %s)\n",debugstr_w(szName),
725 debugstr_w(szValue));
727 rc = MSI_GetPropertyW(package,szName,0,&sz);
728 if (rc==ERROR_MORE_DATA || rc == ERROR_SUCCESS)
730 sprintfW(Query,Update,szName);
732 row = MSI_CreateRecord(1);
733 MSI_RecordSetStringW(row,1,szValue);
736 else
738 strcpyW(Query,Insert);
740 row = MSI_CreateRecord(2);
741 MSI_RecordSetStringW(row,1,szName);
742 MSI_RecordSetStringW(row,2,szValue);
746 rc = MSI_DatabaseOpenViewW(package->db,Query,&view);
747 if (rc!= ERROR_SUCCESS)
749 msiobj_release(&row->hdr);
750 return rc;
753 rc = MSI_ViewExecute(view,row);
755 msiobj_release(&row->hdr);
756 MSI_ViewClose(view);
757 msiobj_release(&view->hdr);
759 return rc;
762 UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue)
764 MSIPACKAGE *package;
765 UINT ret;
767 if (NULL == szName)
768 return ERROR_INVALID_PARAMETER;
769 if (NULL == szValue)
770 return ERROR_INVALID_PARAMETER;
772 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
773 if( !package )
774 return ERROR_INVALID_HANDLE;
775 ret = MSI_SetPropertyW( package, szName, szValue);
776 msiobj_release( &package->hdr );
777 return ret;
780 static UINT MSI_GetPropertyRow(MSIPACKAGE *package, LPCWSTR szName, MSIRECORD **row)
782 MSIQUERY *view;
783 UINT rc, sz;
784 static const WCHAR select[]=
785 {'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ',
786 'F','R','O','M',' ' ,'`','_','P','r','o','p','e','r','t','y','`',
787 ' ','W','H','E','R','E',' ' ,'`','_','P','r','o','p','e','r','t','y','`',
788 '=','\'','%','s','\'',0};
789 LPWSTR query;
791 if (!szName)
792 return ERROR_INVALID_PARAMETER;
794 sz = sizeof select + strlenW(szName)*sizeof(WCHAR);
795 query = msi_alloc( sz);
796 sprintfW(query,select,szName);
798 rc = MSI_DatabaseOpenViewW(package->db, query, &view);
799 msi_free(query);
800 if (rc == ERROR_SUCCESS)
802 rc = MSI_ViewExecute(view, 0);
803 if (rc == ERROR_SUCCESS)
804 rc = MSI_ViewFetch(view,row);
806 MSI_ViewClose(view);
807 msiobj_release(&view->hdr);
810 return rc;
813 UINT MSI_GetPropertyW(MSIPACKAGE *package, LPCWSTR szName,
814 LPWSTR szValueBuf, DWORD* pchValueBuf)
816 MSIRECORD *row;
817 UINT rc;
819 rc = MSI_GetPropertyRow(package, szName, &row);
821 if (*pchValueBuf > 0)
822 szValueBuf[0] = 0;
824 if (rc == ERROR_SUCCESS)
826 rc = MSI_RecordGetStringW(row,1,szValueBuf,pchValueBuf);
827 msiobj_release(&row->hdr);
830 if (rc == ERROR_SUCCESS)
831 TRACE("returning %s for property %s\n", debugstr_w(szValueBuf),
832 debugstr_w(szName));
833 else if (rc == ERROR_MORE_DATA)
834 TRACE("need %li sized buffer for %s\n", *pchValueBuf,
835 debugstr_w(szName));
836 else
838 *pchValueBuf = 0;
839 TRACE("property %s not found\n", debugstr_w(szName));
842 return rc;
845 UINT MSI_GetPropertyA(MSIPACKAGE *package, LPCSTR szName,
846 LPSTR szValueBuf, DWORD* pchValueBuf)
848 MSIRECORD *row;
849 UINT rc;
850 LPWSTR szwName = NULL;
852 if (*pchValueBuf > 0)
853 szValueBuf[0] = 0;
855 if( szName )
857 szwName = strdupAtoW( szName );
858 if (!szwName)
859 return ERROR_NOT_ENOUGH_MEMORY;
862 rc = MSI_GetPropertyRow(package, szwName, &row);
863 if (rc == ERROR_SUCCESS)
865 rc = MSI_RecordGetStringA(row,1,szValueBuf,pchValueBuf);
866 msiobj_release(&row->hdr);
869 if (rc == ERROR_SUCCESS)
870 TRACE("returning %s for property %s\n", debugstr_a(szValueBuf),
871 debugstr_a(szName));
872 else if (rc == ERROR_MORE_DATA)
873 TRACE("need %ld sized buffer for %s\n", *pchValueBuf,
874 debugstr_a(szName));
875 else
877 *pchValueBuf = 0;
878 TRACE("property not found\n");
880 msi_free( szwName );
882 return rc;
885 UINT WINAPI MsiGetPropertyA(MSIHANDLE hInstall, LPCSTR szName, LPSTR szValueBuf, DWORD* pchValueBuf)
887 MSIPACKAGE *package;
888 UINT ret;
890 TRACE("%lu %s %p\n", hInstall, debugstr_a(szName), pchValueBuf);
892 if (0 == hInstall)
893 return ERROR_INVALID_HANDLE;
894 if (NULL == szName)
895 return ERROR_INVALID_PARAMETER;
896 if (NULL != szValueBuf && NULL == pchValueBuf)
897 return ERROR_INVALID_PARAMETER;
899 /* This was tested against native msi */
900 if (NULL == szValueBuf && NULL != pchValueBuf)
901 *pchValueBuf = 0;
903 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
904 if (!package)
905 return ERROR_INVALID_HANDLE;
906 ret = MSI_GetPropertyA(package, szName, szValueBuf, pchValueBuf );
907 msiobj_release( &package->hdr );
909 /* MsiGetProperty does not return error codes on missing properties */
910 if (ret != ERROR_MORE_DATA)
911 ret = ERROR_SUCCESS;
913 return ret;
917 UINT WINAPI MsiGetPropertyW(MSIHANDLE hInstall, LPCWSTR szName,
918 LPWSTR szValueBuf, DWORD* pchValueBuf)
920 MSIPACKAGE *package;
921 UINT ret;
923 TRACE("%lu %s %p\n", hInstall, debugstr_w(szName), pchValueBuf);
925 if (0 == hInstall)
926 return ERROR_INVALID_HANDLE;
927 if (NULL == szName)
928 return ERROR_INVALID_PARAMETER;
929 if (NULL != szValueBuf && NULL == pchValueBuf)
930 return ERROR_INVALID_PARAMETER;
932 /* This was tested against native msi */
933 if (NULL == szValueBuf && NULL != pchValueBuf)
934 *pchValueBuf = 0;
936 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
937 if (!package)
938 return ERROR_INVALID_HANDLE;
939 ret = MSI_GetPropertyW(package, szName, szValueBuf, pchValueBuf );
940 msiobj_release( &package->hdr );
942 /* MsiGetProperty does not return error codes on missing properties */
943 if (ret != ERROR_MORE_DATA)
944 ret = ERROR_SUCCESS;
946 return ret;