Free allocated buffers.
[wine/wine64.git] / dlls / msi / package.c
blobcd54f61c7f18025ee5f325403702ea16dc568515
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 "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"
41 WINE_DEFAULT_DEBUG_CHANNEL(msi);
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.
49 #define LPCTSTR LPCWSTR
51 void MSI_FreePackage( MSIOBJECTHDR *arg)
53 MSIPACKAGE *package= (MSIPACKAGE*) arg;
55 ACTION_remove_tracked_tempfiles(package);
56 ACTION_free_package_structures(package);
58 msiobj_release( &package->db->hdr );
61 UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
63 LPWSTR szwPack = NULL;
64 UINT len, ret;
66 TRACE("%s %p\n",debugstr_a(szPackage), phPackage);
68 if( szPackage )
70 len = MultiByteToWideChar( CP_ACP, 0, szPackage, -1, NULL, 0 );
71 szwPack = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
72 if( szwPack )
73 MultiByteToWideChar( CP_ACP, 0, szPackage, -1, szwPack, len );
76 ret = MsiOpenPackageW( szwPack, phPackage );
78 if( szwPack )
79 HeapFree( GetProcessHeap(), 0, szwPack );
81 return ret;
85 static const UINT clone_properties(MSIDATABASE *db)
87 MSIQUERY * view = NULL;
88 UINT rc;
89 static const WCHAR CreateSql[] = {
90 'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','_','P','r','o',
91 'p','e','r','t','y','`',' ','(',' ','`','_','P','r','o','p','e','r','t',
92 'y','`',' ','C','H','A','R','(','5','6',')',' ','N','O','T',' ','N','U',
93 'L','L',',',' ','`','V','a','l','u','e','`',' ','C','H','A','R','(','9',
94 '8',')',' ','N','O','T',' ','N','U','L','L',' ','P','R','I','M','A','R',
95 'Y',' ','K','E','Y',' ','`','_','P','r','o','p','e','r','t','y','`',')',0};
96 static const WCHAR Query[] = {
97 'S','E','L','E','C','T',' ','*',' ',
98 'f','r','o','m',' ','P','r','o','p','e','r','t','y',0};
99 static const WCHAR Insert[] = {
100 'I','N','S','E','R','T',' ','i','n','t','o',' ',
101 '`','_','P','r','o','p','e','r','t','y','`',' ',
102 '(','`','_','P','r','o','p','e','r','t','y','`',',',
103 '`','V','a','l','u','e','`',')',' ',
104 'V','A','L','U','E','S',' ','(','?',')',0};
106 /* create the temporary properties table */
107 rc = MSI_DatabaseOpenViewW(db, CreateSql, &view);
108 if (rc != ERROR_SUCCESS)
109 return rc;
110 rc = MSI_ViewExecute(view,0);
111 MSI_ViewClose(view);
112 msiobj_release(&view->hdr);
113 if (rc != ERROR_SUCCESS)
114 return rc;
116 /* clone the existing properties */
117 rc = MSI_DatabaseOpenViewW(db, Query, &view);
118 if (rc != ERROR_SUCCESS)
119 return rc;
121 rc = MSI_ViewExecute(view, 0);
122 if (rc != ERROR_SUCCESS)
124 MSI_ViewClose(view);
125 msiobj_release(&view->hdr);
126 return rc;
128 while (1)
130 MSIRECORD * row;
131 MSIQUERY * view2;
133 rc = MSI_ViewFetch(view,&row);
134 if (rc != ERROR_SUCCESS)
135 break;
137 rc = MSI_DatabaseOpenViewW(db,Insert,&view2);
138 if (rc!= ERROR_SUCCESS)
139 continue;
140 rc = MSI_ViewExecute(view2,row);
141 MSI_ViewClose(view2);
142 msiobj_release(&view2->hdr);
144 if (rc == ERROR_SUCCESS)
145 msiobj_release(&row->hdr);
147 MSI_ViewClose(view);
148 msiobj_release(&view->hdr);
150 return rc;
154 * There are a whole slew of these we need to set
157 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/properties.asp
159 static VOID set_installer_properties(MSIPACKAGE *package)
161 WCHAR pth[MAX_PATH];
162 WCHAR *ptr;
163 OSVERSIONINFOA OSVersion;
164 DWORD verval;
165 WCHAR verstr[10], msiver[10];
167 static const WCHAR cszbs[]={'\\',0};
168 static const WCHAR CFF[] =
169 {'C','o','m','m','o','n','F','i','l','e','s','F','o','l','d','e','r',0};
170 static const WCHAR PFF[] =
171 {'P','r','o','g','r','a','m','F','i','l','e','s','F','o','l','d','e','r',0};
172 static const WCHAR CADF[] =
173 {'C','o','m','m','o','n','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
174 static const WCHAR FaF[] =
175 {'F','a','v','o','r','i','t','e','s','F','o','l','d','e','r',0};
176 static const WCHAR FoF[] =
177 {'F','o','n','t','s','F','o','l','d','e','r',0};
178 static const WCHAR SendTF[] =
179 {'S','e','n','d','T','o','F','o','l','d','e','r',0};
180 static const WCHAR SMF[] =
181 {'S','t','a','r','t','M','e','n','u','F','o','l','d','e','r',0};
182 static const WCHAR StF[] =
183 {'S','t','a','r','t','u','p','F','o','l','d','e','r',0};
184 static const WCHAR TemplF[] =
185 {'T','e','m','p','l','a','t','e','F','o','l','d','e','r',0};
186 static const WCHAR DF[] =
187 {'D','e','s','k','t','o','p','F','o','l','d','e','r',0};
188 static const WCHAR PMF[] =
189 {'P','r','o','g','r','a','m','M','e','n','u','F','o','l','d','e','r',0};
190 static const WCHAR ATF[] =
191 {'A','d','m','i','n','T','o','o','l','s','F','o','l','d','e','r',0};
192 static const WCHAR ADF[] =
193 {'A','p','p','D','a','t','a','F','o','l','d','e','r',0};
194 static const WCHAR SF[] =
195 {'S','y','s','t','e','m','F','o','l','d','e','r',0};
196 static const WCHAR SF16[] =
197 {'S','y','s','t','e','m','1','6','F','o','l','d','e','r',0};
198 static const WCHAR LADF[] =
199 {'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
200 static const WCHAR MPF[] =
201 {'M','y','P','i','c','t','u','r','e','s','F','o','l','d','e','r',0};
202 static const WCHAR PF[] =
203 {'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0};
204 static const WCHAR WF[] =
205 {'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
206 static const WCHAR WV[] =
207 {'W','i','n','d','o','w','s','V','o','l','u','m','e',0};
208 static const WCHAR TF[]=
209 {'T','e','m','p','F','o','l','d','e','r',0};
210 static const WCHAR szAdminUser[] =
211 {'A','d','m','i','n','U','s','e','r',0};
212 static const WCHAR szPriv[] =
213 {'P','r','i','v','i','l','e','g','e','d',0};
214 static const WCHAR szOne[] =
215 {'1',0};
216 static const WCHAR v9x[] = { 'V','e','r','s','i','o','n','9','X',0 };
217 static const WCHAR vNT[] = { 'V','e','r','s','i','o','n','N','T',0 };
218 static const WCHAR szFormat[] = {'%','l','i',0};
219 static const WCHAR szWinBuild[] =
220 {'W','i','n','d','o','w','s','B','u','i','l','d', 0 };
221 static const WCHAR szSPL[] =
222 {'S','e','r','v','i','c','e','P','a','c','k','L','e','v','e','l',0 };
223 static const WCHAR szSix[] = {'6',0 };
225 static const WCHAR szVersionMsi[] = { 'V','e','r','s','i','o','n','M','s','i',0 };
226 static const WCHAR szFormat2[] = {'%','l','i','.','%','l','i',0};
227 /* Screen properties */
228 static const WCHAR szScreenX[] = {'S','c','r','e','e','n','X',0};
229 static const WCHAR szScreenY[] = {'S','c','r','e','e','n','Y',0};
230 static const WCHAR szColorBits[] = {'C','o','l','o','r','B','i','t','s',0};
231 static const WCHAR szScreenFormat[] = {'%','d',0};
234 * Other things I notice set
236 SystemLanguageID
237 ComputerName
238 UserLanguageID
239 LogonUser
240 VirtualMemory
241 PhysicalMemory
242 Intel
243 ShellAdvSupport
244 DefaultUIFont
245 VersionDatabase
246 PackagecodeChanging
247 ProductState
248 CaptionHeight
249 BorderTop
250 BorderSide
251 TextHeight
252 RedirectedDllSupport
253 Time
254 Date
255 Privileged
258 SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES_COMMON,NULL,0,pth);
259 strcatW(pth,cszbs);
260 MSI_SetPropertyW(package, CFF, pth);
262 SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES,NULL,0,pth);
263 strcatW(pth,cszbs);
264 MSI_SetPropertyW(package, PFF, pth);
266 SHGetFolderPathW(NULL,CSIDL_COMMON_APPDATA,NULL,0,pth);
267 strcatW(pth,cszbs);
268 MSI_SetPropertyW(package, CADF, pth);
270 SHGetFolderPathW(NULL,CSIDL_FAVORITES,NULL,0,pth);
271 strcatW(pth,cszbs);
272 MSI_SetPropertyW(package, FaF, pth);
274 SHGetFolderPathW(NULL,CSIDL_FONTS,NULL,0,pth);
275 strcatW(pth,cszbs);
276 MSI_SetPropertyW(package, FoF, pth);
278 SHGetFolderPathW(NULL,CSIDL_SENDTO,NULL,0,pth);
279 strcatW(pth,cszbs);
280 MSI_SetPropertyW(package, SendTF, pth);
282 SHGetFolderPathW(NULL,CSIDL_STARTMENU,NULL,0,pth);
283 strcatW(pth,cszbs);
284 MSI_SetPropertyW(package, SMF, pth);
286 SHGetFolderPathW(NULL,CSIDL_STARTUP,NULL,0,pth);
287 strcatW(pth,cszbs);
288 MSI_SetPropertyW(package, StF, pth);
290 SHGetFolderPathW(NULL,CSIDL_TEMPLATES,NULL,0,pth);
291 strcatW(pth,cszbs);
292 MSI_SetPropertyW(package, TemplF, pth);
294 SHGetFolderPathW(NULL,CSIDL_DESKTOP,NULL,0,pth);
295 strcatW(pth,cszbs);
296 MSI_SetPropertyW(package, DF, pth);
298 SHGetFolderPathW(NULL,CSIDL_PROGRAMS,NULL,0,pth);
299 strcatW(pth,cszbs);
300 MSI_SetPropertyW(package, PMF, pth);
302 SHGetFolderPathW(NULL,CSIDL_ADMINTOOLS,NULL,0,pth);
303 strcatW(pth,cszbs);
304 MSI_SetPropertyW(package, ATF, pth);
306 SHGetFolderPathW(NULL,CSIDL_APPDATA,NULL,0,pth);
307 strcatW(pth,cszbs);
308 MSI_SetPropertyW(package, ADF, pth);
310 SHGetFolderPathW(NULL,CSIDL_SYSTEM,NULL,0,pth);
311 strcatW(pth,cszbs);
312 MSI_SetPropertyW(package, SF, pth);
313 MSI_SetPropertyW(package, SF16, pth);
315 SHGetFolderPathW(NULL,CSIDL_LOCAL_APPDATA,NULL,0,pth);
316 strcatW(pth,cszbs);
317 MSI_SetPropertyW(package, LADF, pth);
319 SHGetFolderPathW(NULL,CSIDL_MYPICTURES,NULL,0,pth);
320 strcatW(pth,cszbs);
321 MSI_SetPropertyW(package, MPF, pth);
323 SHGetFolderPathW(NULL,CSIDL_PERSONAL,NULL,0,pth);
324 strcatW(pth,cszbs);
325 MSI_SetPropertyW(package, PF, pth);
327 SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
328 strcatW(pth,cszbs);
329 MSI_SetPropertyW(package, WF, pth);
331 SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
332 ptr = strchrW(pth,'\\');
333 if (ptr)
334 *(ptr+1) = 0;
335 MSI_SetPropertyW(package, WV, pth);
337 GetTempPathW(MAX_PATH,pth);
338 MSI_SetPropertyW(package, TF, pth);
341 /* in a wine environment the user is always admin and privileged */
342 MSI_SetPropertyW(package,szAdminUser,szOne);
343 MSI_SetPropertyW(package,szPriv,szOne);
345 /* set the os things */
346 OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
347 GetVersionExA(&OSVersion);
348 verval = OSVersion.dwMinorVersion+OSVersion.dwMajorVersion*100;
349 sprintfW(verstr,szFormat,verval);
350 switch (OSVersion.dwPlatformId)
352 case VER_PLATFORM_WIN32_WINDOWS:
353 MSI_SetPropertyW(package,v9x,verstr);
354 break;
355 case VER_PLATFORM_WIN32_NT:
356 MSI_SetPropertyW(package,vNT,verstr);
357 break;
359 sprintfW(verstr,szFormat,OSVersion.dwBuildNumber);
360 MSI_SetPropertyW(package,szWinBuild,verstr);
361 /* just fudge this */
362 MSI_SetPropertyW(package,szSPL,szSix);
364 sprintfW( msiver, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION);
365 MSI_SetPropertyW( package, szVersionMsi, msiver );
367 /* Screen properties. FIXME: need to get correct values from system */
368 sprintfW( msiver, szScreenFormat, 800);
369 MSI_SetPropertyW( package, szScreenX, msiver );
370 sprintfW( msiver, szScreenFormat, 600);
371 MSI_SetPropertyW( package, szScreenY, msiver );
372 sprintfW( msiver, szScreenFormat, 24);
373 MSI_SetPropertyW( package, szColorBits, msiver );
376 UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
378 UINT rc;
379 MSIDATABASE *db = NULL;
380 MSIPACKAGE *package = NULL;
381 WCHAR uilevel[10];
382 UINT ret = ERROR_FUNCTION_FAILED;
384 static const WCHAR OriginalDatabase[] =
385 {'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
386 static const WCHAR Database[] =
387 {'D','A','T','A','B','A','S','E',0};
388 static const WCHAR szpi[] = {'%','i',0};
389 static const WCHAR szLevel[] = { 'U','I','L','e','v','e','l',0 };
391 TRACE("%s %p\n",debugstr_w(szPackage), pPackage);
393 if (szPackage[0] == '#')
395 INT handle = atoiW(&szPackage[1]);
396 db = msihandle2msiinfo( handle , MSIHANDLETYPE_DATABASE);
398 else
400 rc = MSI_OpenDatabaseW(szPackage, MSIDBOPEN_READONLY, &db);
401 if (rc != ERROR_SUCCESS)
402 return ERROR_FUNCTION_FAILED;
405 package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE),
406 MSI_FreePackage );
408 if (package)
410 msiobj_addref( &db->hdr );
412 package->db = db;
413 package->features = NULL;
414 package->folders = NULL;
415 package->components = NULL;
416 package->files = NULL;
417 package->loaded_features = 0;
418 package->loaded_folders = 0;
419 package->loaded_components= 0;
420 package->loaded_files = 0;
421 package->ActionFormat = NULL;
422 package->LastAction = NULL;
424 /* OK, here is where we do a slew of things to the database to
425 * prep for all that is to come as a package */
427 clone_properties(db);
428 set_installer_properties(package);
429 MSI_SetPropertyW(package, OriginalDatabase, szPackage);
430 MSI_SetPropertyW(package, Database, szPackage);
431 sprintfW(uilevel,szpi,gUILevel);
432 MSI_SetPropertyW(package, szLevel, uilevel);
434 msiobj_addref( &package->hdr );
435 *pPackage = package;
436 ret = ERROR_SUCCESS;
439 if( package )
440 msiobj_release( &package->hdr );
441 if( db )
442 msiobj_release( &db->hdr );
444 return ret;
447 UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
449 MSIPACKAGE *package = NULL;
450 UINT ret;
452 ret = MSI_OpenPackageW( szPackage, &package);
453 if( ret == ERROR_SUCCESS )
455 *phPackage = alloc_msihandle( &package->hdr );
456 msiobj_release( &package->hdr );
458 return ret;
461 UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
463 FIXME("%s 0x%08lx %p\n",debugstr_a(szPackage), dwOptions, phPackage);
464 return ERROR_CALL_NOT_IMPLEMENTED;
467 UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
469 FIXME("%s 0x%08lx %p\n",debugstr_w(szPackage), dwOptions, phPackage);
470 return ERROR_CALL_NOT_IMPLEMENTED;
473 MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
475 MSIPACKAGE *package;
476 MSIHANDLE handle = 0;
478 TRACE("(%ld)\n",hInstall);
480 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
481 if( package)
483 handle = alloc_msihandle( &package->db->hdr );
484 msiobj_release( &package->hdr );
487 return handle;
490 INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType,
491 MSIRECORD *record)
493 DWORD log_type = 0;
494 LPWSTR message;
495 DWORD sz;
496 DWORD total_size = 0;
497 INT msg_field=1;
498 INT i;
499 INT rc;
500 char *msg;
501 int len;
503 TRACE("%x \n",eMessageType);
504 rc = 0;
506 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ERROR)
507 log_type |= INSTALLLOGMODE_ERROR;
508 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_WARNING)
509 log_type |= INSTALLLOGMODE_WARNING;
510 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_USER)
511 log_type |= INSTALLLOGMODE_USER;
512 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INFO)
513 log_type |= INSTALLLOGMODE_INFO;
514 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA)
515 log_type |= INSTALLLOGMODE_COMMONDATA;
516 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART)
517 log_type |= INSTALLLOGMODE_ACTIONSTART;
518 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONDATA)
519 log_type |= INSTALLLOGMODE_ACTIONDATA;
520 /* just a guess */
521 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_PROGRESS)
522 log_type |= 0x800;
524 message = HeapAlloc(GetProcessHeap(),0,1*sizeof (WCHAR));
525 message[0]=0;
526 msg_field = MSI_RecordGetFieldCount(record);
527 for (i = 1; i <= msg_field; i++)
529 LPWSTR tmp;
530 WCHAR number[3];
531 const static WCHAR format[] = { '%','i',':',' ',0};
532 const static WCHAR space[] = { ' ',0};
533 sz = 0;
534 MSI_RecordGetStringW(record,i,NULL,&sz);
535 sz+=4;
536 total_size+=sz*sizeof(WCHAR);
537 tmp = HeapAlloc(GetProcessHeap(),0,sz*sizeof(WCHAR));
538 message = HeapReAlloc(GetProcessHeap(),0,message,total_size*sizeof (WCHAR));
540 MSI_RecordGetStringW(record,i,tmp,&sz);
542 if (msg_field > 1)
544 sprintfW(number,format,i);
545 strcatW(message,number);
547 strcatW(message,tmp);
548 if (msg_field > 1)
549 strcatW(message,space);
551 HeapFree(GetProcessHeap(),0,tmp);
554 TRACE("(%p %lx %lx %s)\n",gUIHandler, gUIFilter, log_type,
555 debugstr_w(message));
557 /* convert it to ASCII */
558 len = WideCharToMultiByte( CP_ACP, 0, message, -1,
559 NULL, 0, NULL, NULL );
560 msg = HeapAlloc( GetProcessHeap(), 0, len );
561 WideCharToMultiByte( CP_ACP, 0, message, -1,
562 msg, len, NULL, NULL );
564 if (gUIHandler && (gUIFilter & log_type))
566 rc = gUIHandler(gUIContext,eMessageType,msg);
569 if ((!rc) && (gszLogFile[0]) && !((eMessageType & 0xff000000) ==
570 INSTALLMESSAGE_PROGRESS))
572 DWORD write;
573 HANDLE log_file = CreateFileW(gszLogFile,GENERIC_WRITE, 0, NULL,
574 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
576 if (log_file != INVALID_HANDLE_VALUE)
578 SetFilePointer(log_file,0, NULL, FILE_END);
579 WriteFile(log_file,msg,strlen(msg),&write,NULL);
580 WriteFile(log_file,"\n",1,&write,NULL);
581 CloseHandle(log_file);
584 HeapFree( GetProcessHeap(), 0, msg );
586 HeapFree(GetProcessHeap(),0,message);
587 return ERROR_SUCCESS;
590 INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
591 MSIHANDLE hRecord)
593 UINT ret = ERROR_INVALID_HANDLE;
594 MSIPACKAGE *package = NULL;
595 MSIRECORD *record = NULL;
597 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
598 if( !package )
599 goto out;
601 record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD );
602 if( !record )
603 goto out;
605 ret = MSI_ProcessMessage( package, eMessageType, record );
607 out:
608 if( package )
609 msiobj_release( &package->hdr );
610 if( record )
611 msiobj_release( &record->hdr );
613 return ret;
616 /* property code */
617 UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue)
619 LPWSTR szwName = NULL, szwValue = NULL;
620 UINT hr = ERROR_INSTALL_FAILURE;
621 UINT len;
623 if (0 == hInstall) {
624 return ERROR_INVALID_HANDLE;
626 if (NULL == szName) {
627 return ERROR_INVALID_PARAMETER;
629 if (NULL == szValue) {
630 return ERROR_INVALID_PARAMETER;
633 len = MultiByteToWideChar( CP_ACP, 0, szName, -1, NULL, 0 );
634 szwName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
635 if( !szwName )
636 goto end;
637 MultiByteToWideChar( CP_ACP, 0, szName, -1, szwName, len );
639 len = MultiByteToWideChar( CP_ACP, 0, szValue, -1, NULL, 0 );
640 szwValue = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
641 if( !szwValue)
642 goto end;
643 MultiByteToWideChar( CP_ACP, 0, szValue , -1, szwValue, len );
645 hr = MsiSetPropertyW( hInstall, szwName, szwValue);
647 end:
648 if( szwName )
649 HeapFree( GetProcessHeap(), 0, szwName );
650 if( szwValue )
651 HeapFree( GetProcessHeap(), 0, szwValue );
653 return hr;
656 UINT MSI_SetPropertyW( MSIPACKAGE *package, LPCWSTR szName, LPCWSTR szValue)
658 MSIQUERY *view;
659 MSIRECORD *row;
660 UINT rc;
661 DWORD sz = 0;
662 static const WCHAR Insert[]=
663 {'I','N','S','E','R','T',' ','i','n','t','o',' ','`','_','P','r','o','p'
664 ,'e','r','t','y','`',' ','(','`','_','P','r','o','p','e','r','t','y','`'
665 ,',','`','V','a','l','u','e','`',')',' ','V','A','L','U','E','S'
666 ,' ','(','?',')',0};
667 static const WCHAR Update[]=
668 {'U','P','D','A','T','E',' ','_','P','r','o','p','e'
669 ,'r','t','y',' ','s','e','t',' ','`','V','a','l','u','e','`',' ','='
670 ,' ','?',' ','w','h','e','r','e',' ','`','_','P','r','o','p'
671 ,'e','r','t','y','`',' ','=',' ','\'','%','s','\'',0};
672 WCHAR Query[1024];
674 TRACE("Setting property (%s %s)\n",debugstr_w(szName),
675 debugstr_w(szValue));
677 rc = MSI_GetPropertyW(package,szName,0,&sz);
678 if (rc==ERROR_MORE_DATA || rc == ERROR_SUCCESS)
680 sprintfW(Query,Update,szName);
682 row = MSI_CreateRecord(1);
683 MSI_RecordSetStringW(row,1,szValue);
686 else
688 strcpyW(Query,Insert);
690 row = MSI_CreateRecord(2);
691 MSI_RecordSetStringW(row,1,szName);
692 MSI_RecordSetStringW(row,2,szValue);
696 rc = MSI_DatabaseOpenViewW(package->db,Query,&view);
697 if (rc!= ERROR_SUCCESS)
699 msiobj_release(&row->hdr);
700 return rc;
703 rc = MSI_ViewExecute(view,row);
705 msiobj_release(&row->hdr);
706 MSI_ViewClose(view);
707 msiobj_release(&view->hdr);
709 return rc;
712 UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue)
714 MSIPACKAGE *package;
715 UINT ret;
717 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
718 if( !package)
719 return ERROR_INVALID_HANDLE;
720 ret = MSI_SetPropertyW( package, szName, szValue);
721 msiobj_release( &package->hdr );
722 return ret;
725 static UINT MSI_GetPropertyRow(MSIPACKAGE *package, LPCWSTR szName, MSIRECORD **row)
727 MSIQUERY *view;
728 UINT rc, sz;
729 static const WCHAR select[]=
730 {'s','e','l','e','c','t',' ','V','a','l','u','e',' ','f','r','o','m',' '
731 ,'_','P','r','o','p','e','r','t','y',' ','w','h','e','r','e',' '
732 ,'_','P','r','o','p','e','r','t','y','=','`','%','s','`',0};
733 LPWSTR query;
735 if (!szName)
736 return ERROR_INVALID_PARAMETER;
738 sz = sizeof select + strlenW(szName)*sizeof(WCHAR);
739 query = HeapAlloc(GetProcessHeap(), 0, sz);
740 sprintfW(query,select,szName);
742 rc = MSI_DatabaseOpenViewW(package->db, query, &view);
743 HeapFree(GetProcessHeap(), 0, query);
744 if (rc == ERROR_SUCCESS)
746 rc = MSI_ViewExecute(view, 0);
747 if (rc == ERROR_SUCCESS)
748 rc = MSI_ViewFetch(view,row);
750 MSI_ViewClose(view);
751 msiobj_release(&view->hdr);
754 return rc;
757 UINT MSI_GetPropertyW(MSIPACKAGE *package, LPCWSTR szName,
758 LPWSTR szValueBuf, DWORD* pchValueBuf)
760 MSIRECORD *row;
761 UINT rc;
763 rc = MSI_GetPropertyRow(package, szName, &row);
765 if (*pchValueBuf > 0)
766 szValueBuf[0] = 0;
768 if (rc == ERROR_SUCCESS)
770 rc = MSI_RecordGetStringW(row,1,szValueBuf,pchValueBuf);
771 msiobj_release(&row->hdr);
774 if (rc == ERROR_SUCCESS)
775 TRACE("returning %s for property %s\n", debugstr_w(szValueBuf),
776 debugstr_w(szName));
777 else if (rc == ERROR_MORE_DATA)
778 TRACE("need %li sized buffer for %s\n", *pchValueBuf,
779 debugstr_w(szName));
780 else
782 *pchValueBuf = 0;
783 TRACE("property not found\n");
786 return rc;
789 UINT MSI_GetPropertyA(MSIPACKAGE *package, LPCSTR szName,
790 LPSTR szValueBuf, DWORD* pchValueBuf)
792 MSIRECORD *row;
793 UINT rc, len;
794 LPWSTR szwName;
796 if (*pchValueBuf > 0)
797 szValueBuf[0] = 0;
799 len = MultiByteToWideChar( CP_ACP, 0, szName, -1, NULL, 0 );
800 szwName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
801 if (!szwName)
802 return ERROR_NOT_ENOUGH_MEMORY;
803 MultiByteToWideChar( CP_ACP, 0, szName, -1, szwName, len );
805 rc = MSI_GetPropertyRow(package, szwName, &row);
806 if (rc == ERROR_SUCCESS)
808 rc = MSI_RecordGetStringA(row,1,szValueBuf,pchValueBuf);
809 msiobj_release(&row->hdr);
812 if (rc == ERROR_SUCCESS)
813 TRACE("returning %s for property %s\n", debugstr_a(szValueBuf),
814 debugstr_a(szName));
815 else if (rc == ERROR_MORE_DATA)
816 TRACE("need %ld sized buffer for %s\n", *pchValueBuf,
817 debugstr_a(szName));
818 else
820 *pchValueBuf = 0;
821 TRACE("property not found\n");
823 HeapFree( GetProcessHeap(), 0, szwName );
825 return rc;
828 UINT WINAPI MsiGetPropertyA(MSIHANDLE hInstall, LPCSTR szName, LPSTR szValueBuf, DWORD* pchValueBuf)
830 MSIPACKAGE *package;
831 UINT ret;
833 TRACE("%lu %s %lu\n", hInstall, debugstr_a(szName), *pchValueBuf);
835 if (0 == hInstall)
836 return ERROR_INVALID_HANDLE;
837 if (NULL == szName)
838 return ERROR_INVALID_PARAMETER;
839 if (NULL != szValueBuf && NULL == pchValueBuf)
840 return ERROR_INVALID_PARAMETER;
842 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
843 if (!package)
844 return ERROR_INVALID_HANDLE;
845 ret = MSI_GetPropertyA(package, szName, szValueBuf, pchValueBuf );
846 msiobj_release( &package->hdr );
847 return ret;
851 UINT WINAPI MsiGetPropertyW(MSIHANDLE hInstall, LPCWSTR szName,
852 LPWSTR szValueBuf, DWORD* pchValueBuf)
854 MSIPACKAGE *package;
855 UINT ret;
857 if (0 == hInstall)
858 return ERROR_INVALID_HANDLE;
859 if (NULL == szName)
860 return ERROR_INVALID_PARAMETER;
861 if (NULL != szValueBuf && NULL == pchValueBuf)
862 return ERROR_INVALID_PARAMETER;
864 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
865 if (!package)
866 return ERROR_INVALID_HANDLE;
867 ret = MSI_GetPropertyW(package, szName, szValueBuf, pchValueBuf );
868 msiobj_release( &package->hdr );
869 return ret;