Do not check for non NULL pointer before HeapFree'ing it. It's
[wine.git] / dlls / msi / package.c
blobda65470e22fe66e57ed5b279251ed7f92a77e1d3
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 void MSI_FreePackage( MSIOBJECTHDR *arg)
54 MSIPACKAGE *package= (MSIPACKAGE*) arg;
56 ACTION_remove_tracked_tempfiles(package);
57 ACTION_free_package_structures(package);
59 msiobj_release( &package->db->hdr );
62 UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
64 LPWSTR szwPack = NULL;
65 UINT len, ret;
67 TRACE("%s %p\n",debugstr_a(szPackage), phPackage);
69 if( szPackage )
71 len = MultiByteToWideChar( CP_ACP, 0, szPackage, -1, NULL, 0 );
72 szwPack = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
73 if( szwPack )
74 MultiByteToWideChar( CP_ACP, 0, szPackage, -1, szwPack, len );
77 ret = MsiOpenPackageW( szwPack, phPackage );
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], bufstr[20];
166 HDC dc;
168 static const WCHAR cszbs[]={'\\',0};
169 static const WCHAR CFF[] =
170 {'C','o','m','m','o','n','F','i','l','e','s','F','o','l','d','e','r',0};
171 static const WCHAR PFF[] =
172 {'P','r','o','g','r','a','m','F','i','l','e','s','F','o','l','d','e','r',0};
173 static const WCHAR CADF[] =
174 {'C','o','m','m','o','n','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
175 static const WCHAR FaF[] =
176 {'F','a','v','o','r','i','t','e','s','F','o','l','d','e','r',0};
177 static const WCHAR FoF[] =
178 {'F','o','n','t','s','F','o','l','d','e','r',0};
179 static const WCHAR SendTF[] =
180 {'S','e','n','d','T','o','F','o','l','d','e','r',0};
181 static const WCHAR SMF[] =
182 {'S','t','a','r','t','M','e','n','u','F','o','l','d','e','r',0};
183 static const WCHAR StF[] =
184 {'S','t','a','r','t','u','p','F','o','l','d','e','r',0};
185 static const WCHAR TemplF[] =
186 {'T','e','m','p','l','a','t','e','F','o','l','d','e','r',0};
187 static const WCHAR DF[] =
188 {'D','e','s','k','t','o','p','F','o','l','d','e','r',0};
189 static const WCHAR PMF[] =
190 {'P','r','o','g','r','a','m','M','e','n','u','F','o','l','d','e','r',0};
191 static const WCHAR ATF[] =
192 {'A','d','m','i','n','T','o','o','l','s','F','o','l','d','e','r',0};
193 static const WCHAR ADF[] =
194 {'A','p','p','D','a','t','a','F','o','l','d','e','r',0};
195 static const WCHAR SF[] =
196 {'S','y','s','t','e','m','F','o','l','d','e','r',0};
197 static const WCHAR SF16[] =
198 {'S','y','s','t','e','m','1','6','F','o','l','d','e','r',0};
199 static const WCHAR LADF[] =
200 {'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
201 static const WCHAR MPF[] =
202 {'M','y','P','i','c','t','u','r','e','s','F','o','l','d','e','r',0};
203 static const WCHAR PF[] =
204 {'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0};
205 static const WCHAR WF[] =
206 {'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
207 static const WCHAR WV[] =
208 {'W','i','n','d','o','w','s','V','o','l','u','m','e',0};
209 static const WCHAR TF[]=
210 {'T','e','m','p','F','o','l','d','e','r',0};
211 static const WCHAR szAdminUser[] =
212 {'A','d','m','i','n','U','s','e','r',0};
213 static const WCHAR szPriv[] =
214 {'P','r','i','v','i','l','e','g','e','d',0};
215 static const WCHAR szOne[] =
216 {'1',0};
217 static const WCHAR v9x[] = { 'V','e','r','s','i','o','n','9','X',0 };
218 static const WCHAR vNT[] = { 'V','e','r','s','i','o','n','N','T',0 };
219 static const WCHAR szFormat[] = {'%','l','i',0};
220 static const WCHAR szWinBuild[] =
221 {'W','i','n','d','o','w','s','B','u','i','l','d', 0 };
222 static const WCHAR szSPL[] =
223 {'S','e','r','v','i','c','e','P','a','c','k','L','e','v','e','l',0 };
224 static const WCHAR szSix[] = {'6',0 };
226 static const WCHAR szVersionMsi[] = { 'V','e','r','s','i','o','n','M','s','i',0 };
227 static const WCHAR szFormat2[] = {'%','l','i','.','%','l','i',0};
228 /* Screen properties */
229 static const WCHAR szScreenX[] = {'S','c','r','e','e','n','X',0};
230 static const WCHAR szScreenY[] = {'S','c','r','e','e','n','Y',0};
231 static const WCHAR szColorBits[] = {'C','o','l','o','r','B','i','t','s',0};
232 static const WCHAR szScreenFormat[] = {'%','d',0};
235 * Other things I notice set
237 SystemLanguageID
238 ComputerName
239 UserLanguageID
240 LogonUser
241 VirtualMemory
242 PhysicalMemory
243 Intel
244 ShellAdvSupport
245 DefaultUIFont
246 VersionDatabase
247 PackagecodeChanging
248 ProductState
249 CaptionHeight
250 BorderTop
251 BorderSide
252 TextHeight
253 RedirectedDllSupport
254 Time
255 Date
256 Privileged
259 SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES_COMMON,NULL,0,pth);
260 strcatW(pth,cszbs);
261 MSI_SetPropertyW(package, CFF, pth);
263 SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES,NULL,0,pth);
264 strcatW(pth,cszbs);
265 MSI_SetPropertyW(package, PFF, pth);
267 SHGetFolderPathW(NULL,CSIDL_COMMON_APPDATA,NULL,0,pth);
268 strcatW(pth,cszbs);
269 MSI_SetPropertyW(package, CADF, pth);
271 SHGetFolderPathW(NULL,CSIDL_FAVORITES,NULL,0,pth);
272 strcatW(pth,cszbs);
273 MSI_SetPropertyW(package, FaF, pth);
275 SHGetFolderPathW(NULL,CSIDL_FONTS,NULL,0,pth);
276 strcatW(pth,cszbs);
277 MSI_SetPropertyW(package, FoF, pth);
279 SHGetFolderPathW(NULL,CSIDL_SENDTO,NULL,0,pth);
280 strcatW(pth,cszbs);
281 MSI_SetPropertyW(package, SendTF, pth);
283 SHGetFolderPathW(NULL,CSIDL_STARTMENU,NULL,0,pth);
284 strcatW(pth,cszbs);
285 MSI_SetPropertyW(package, SMF, pth);
287 SHGetFolderPathW(NULL,CSIDL_STARTUP,NULL,0,pth);
288 strcatW(pth,cszbs);
289 MSI_SetPropertyW(package, StF, pth);
291 SHGetFolderPathW(NULL,CSIDL_TEMPLATES,NULL,0,pth);
292 strcatW(pth,cszbs);
293 MSI_SetPropertyW(package, TemplF, pth);
295 SHGetFolderPathW(NULL,CSIDL_DESKTOP,NULL,0,pth);
296 strcatW(pth,cszbs);
297 MSI_SetPropertyW(package, DF, pth);
299 SHGetFolderPathW(NULL,CSIDL_PROGRAMS,NULL,0,pth);
300 strcatW(pth,cszbs);
301 MSI_SetPropertyW(package, PMF, pth);
303 SHGetFolderPathW(NULL,CSIDL_ADMINTOOLS,NULL,0,pth);
304 strcatW(pth,cszbs);
305 MSI_SetPropertyW(package, ATF, pth);
307 SHGetFolderPathW(NULL,CSIDL_APPDATA,NULL,0,pth);
308 strcatW(pth,cszbs);
309 MSI_SetPropertyW(package, ADF, pth);
311 SHGetFolderPathW(NULL,CSIDL_SYSTEM,NULL,0,pth);
312 strcatW(pth,cszbs);
313 MSI_SetPropertyW(package, SF, pth);
314 MSI_SetPropertyW(package, SF16, pth);
316 SHGetFolderPathW(NULL,CSIDL_LOCAL_APPDATA,NULL,0,pth);
317 strcatW(pth,cszbs);
318 MSI_SetPropertyW(package, LADF, pth);
320 SHGetFolderPathW(NULL,CSIDL_MYPICTURES,NULL,0,pth);
321 strcatW(pth,cszbs);
322 MSI_SetPropertyW(package, MPF, pth);
324 SHGetFolderPathW(NULL,CSIDL_PERSONAL,NULL,0,pth);
325 strcatW(pth,cszbs);
326 MSI_SetPropertyW(package, PF, pth);
328 SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
329 strcatW(pth,cszbs);
330 MSI_SetPropertyW(package, WF, pth);
332 SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
333 ptr = strchrW(pth,'\\');
334 if (ptr)
335 *(ptr+1) = 0;
336 MSI_SetPropertyW(package, WV, pth);
338 GetTempPathW(MAX_PATH,pth);
339 MSI_SetPropertyW(package, TF, pth);
342 /* in a wine environment the user is always admin and privileged */
343 MSI_SetPropertyW(package,szAdminUser,szOne);
344 MSI_SetPropertyW(package,szPriv,szOne);
346 /* set the os things */
347 OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
348 GetVersionExA(&OSVersion);
349 verval = OSVersion.dwMinorVersion+OSVersion.dwMajorVersion*100;
350 sprintfW(verstr,szFormat,verval);
351 switch (OSVersion.dwPlatformId)
353 case VER_PLATFORM_WIN32_WINDOWS:
354 MSI_SetPropertyW(package,v9x,verstr);
355 break;
356 case VER_PLATFORM_WIN32_NT:
357 MSI_SetPropertyW(package,vNT,verstr);
358 break;
360 sprintfW(verstr,szFormat,OSVersion.dwBuildNumber);
361 MSI_SetPropertyW(package,szWinBuild,verstr);
362 /* just fudge this */
363 MSI_SetPropertyW(package,szSPL,szSix);
365 sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION);
366 MSI_SetPropertyW( package, szVersionMsi, bufstr );
368 /* Screen properties. */
369 dc = GetDC(0);
370 sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, HORZRES ) );
371 MSI_SetPropertyW( package, szScreenX, bufstr );
372 sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, VERTRES ));
373 MSI_SetPropertyW( package, szScreenY, bufstr );
374 sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, BITSPIXEL ));
375 MSI_SetPropertyW( package, szColorBits, bufstr );
376 ReleaseDC(0, dc);
379 UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
381 UINT rc;
382 MSIDATABASE *db = NULL;
383 MSIPACKAGE *package = NULL;
384 WCHAR uilevel[10];
385 UINT ret = ERROR_FUNCTION_FAILED;
387 static const WCHAR OriginalDatabase[] =
388 {'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
389 static const WCHAR Database[] =
390 {'D','A','T','A','B','A','S','E',0};
391 static const WCHAR szpi[] = {'%','i',0};
392 static const WCHAR szLevel[] = { 'U','I','L','e','v','e','l',0 };
394 TRACE("%s %p\n",debugstr_w(szPackage), pPackage);
396 if (szPackage[0] == '#')
398 INT handle = atoiW(&szPackage[1]);
399 db = msihandle2msiinfo( handle , MSIHANDLETYPE_DATABASE);
401 else
403 rc = MSI_OpenDatabaseW(szPackage, MSIDBOPEN_READONLY, &db);
404 if (rc != ERROR_SUCCESS)
405 return ERROR_FUNCTION_FAILED;
408 package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE),
409 MSI_FreePackage );
411 if (package)
413 msiobj_addref( &db->hdr );
415 package->db = db;
416 package->features = NULL;
417 package->folders = NULL;
418 package->components = NULL;
419 package->files = NULL;
420 package->loaded_features = 0;
421 package->loaded_folders = 0;
422 package->loaded_components= 0;
423 package->loaded_files = 0;
424 package->ActionFormat = NULL;
425 package->LastAction = NULL;
427 /* OK, here is where we do a slew of things to the database to
428 * prep for all that is to come as a package */
430 clone_properties(db);
431 set_installer_properties(package);
432 MSI_SetPropertyW(package, OriginalDatabase, szPackage);
433 MSI_SetPropertyW(package, Database, szPackage);
434 sprintfW(uilevel,szpi,gUILevel);
435 MSI_SetPropertyW(package, szLevel, uilevel);
437 msiobj_addref( &package->hdr );
438 *pPackage = package;
439 ret = ERROR_SUCCESS;
442 if( package )
443 msiobj_release( &package->hdr );
444 if( db )
445 msiobj_release( &db->hdr );
447 return ret;
450 UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
452 MSIPACKAGE *package = NULL;
453 UINT ret;
455 ret = MSI_OpenPackageW( szPackage, &package);
456 if( ret == ERROR_SUCCESS )
458 *phPackage = alloc_msihandle( &package->hdr );
459 msiobj_release( &package->hdr );
461 return ret;
464 UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
466 FIXME("%s 0x%08lx %p\n",debugstr_a(szPackage), dwOptions, phPackage);
467 return ERROR_CALL_NOT_IMPLEMENTED;
470 UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
472 FIXME("%s 0x%08lx %p\n",debugstr_w(szPackage), dwOptions, phPackage);
473 return ERROR_CALL_NOT_IMPLEMENTED;
476 MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
478 MSIPACKAGE *package;
479 MSIHANDLE handle = 0;
481 TRACE("(%ld)\n",hInstall);
483 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
484 if( package)
486 handle = alloc_msihandle( &package->db->hdr );
487 msiobj_release( &package->hdr );
490 return handle;
493 INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType,
494 MSIRECORD *record)
496 DWORD log_type = 0;
497 LPWSTR message;
498 DWORD sz;
499 DWORD total_size = 0;
500 INT msg_field=1;
501 INT i;
502 INT rc;
503 char *msg;
504 int len;
506 TRACE("%x \n",eMessageType);
507 rc = 0;
509 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ERROR)
510 log_type |= INSTALLLOGMODE_ERROR;
511 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_WARNING)
512 log_type |= INSTALLLOGMODE_WARNING;
513 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_USER)
514 log_type |= INSTALLLOGMODE_USER;
515 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INFO)
516 log_type |= INSTALLLOGMODE_INFO;
517 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA)
518 log_type |= INSTALLLOGMODE_COMMONDATA;
519 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART)
520 log_type |= INSTALLLOGMODE_ACTIONSTART;
521 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONDATA)
522 log_type |= INSTALLLOGMODE_ACTIONDATA;
523 /* just a guess */
524 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_PROGRESS)
525 log_type |= 0x800;
527 message = HeapAlloc(GetProcessHeap(),0,1*sizeof (WCHAR));
528 message[0]=0;
529 msg_field = MSI_RecordGetFieldCount(record);
530 for (i = 1; i <= msg_field; i++)
532 LPWSTR tmp;
533 WCHAR number[3];
534 const static WCHAR format[] = { '%','i',':',' ',0};
535 const static WCHAR space[] = { ' ',0};
536 sz = 0;
537 MSI_RecordGetStringW(record,i,NULL,&sz);
538 sz+=4;
539 total_size+=sz*sizeof(WCHAR);
540 tmp = HeapAlloc(GetProcessHeap(),0,sz*sizeof(WCHAR));
541 message = HeapReAlloc(GetProcessHeap(),0,message,total_size*sizeof (WCHAR));
543 MSI_RecordGetStringW(record,i,tmp,&sz);
545 if (msg_field > 1)
547 sprintfW(number,format,i);
548 strcatW(message,number);
550 strcatW(message,tmp);
551 if (msg_field > 1)
552 strcatW(message,space);
554 HeapFree(GetProcessHeap(),0,tmp);
557 TRACE("(%p %lx %lx %s)\n",gUIHandler, gUIFilter, log_type,
558 debugstr_w(message));
560 /* convert it to ASCII */
561 len = WideCharToMultiByte( CP_ACP, 0, message, -1,
562 NULL, 0, NULL, NULL );
563 msg = HeapAlloc( GetProcessHeap(), 0, len );
564 WideCharToMultiByte( CP_ACP, 0, message, -1,
565 msg, len, NULL, NULL );
567 if (gUIHandler && (gUIFilter & log_type))
569 rc = gUIHandler(gUIContext,eMessageType,msg);
572 if ((!rc) && (gszLogFile[0]) && !((eMessageType & 0xff000000) ==
573 INSTALLMESSAGE_PROGRESS))
575 DWORD write;
576 HANDLE log_file = CreateFileW(gszLogFile,GENERIC_WRITE, 0, NULL,
577 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
579 if (log_file != INVALID_HANDLE_VALUE)
581 SetFilePointer(log_file,0, NULL, FILE_END);
582 WriteFile(log_file,msg,strlen(msg),&write,NULL);
583 WriteFile(log_file,"\n",1,&write,NULL);
584 CloseHandle(log_file);
587 HeapFree( GetProcessHeap(), 0, msg );
589 HeapFree(GetProcessHeap(),0,message);
590 return ERROR_SUCCESS;
593 INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
594 MSIHANDLE hRecord)
596 UINT ret = ERROR_INVALID_HANDLE;
597 MSIPACKAGE *package = NULL;
598 MSIRECORD *record = NULL;
600 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
601 if( !package )
602 goto out;
604 record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD );
605 if( !record )
606 goto out;
608 ret = MSI_ProcessMessage( package, eMessageType, record );
610 out:
611 if( package )
612 msiobj_release( &package->hdr );
613 if( record )
614 msiobj_release( &record->hdr );
616 return ret;
619 /* property code */
620 UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue)
622 LPWSTR szwName = NULL, szwValue = NULL;
623 UINT hr = ERROR_INSTALL_FAILURE;
624 UINT len;
626 if (0 == hInstall) {
627 return ERROR_INVALID_HANDLE;
629 if (NULL == szName) {
630 return ERROR_INVALID_PARAMETER;
632 if (NULL == szValue) {
633 return ERROR_INVALID_PARAMETER;
636 len = MultiByteToWideChar( CP_ACP, 0, szName, -1, NULL, 0 );
637 szwName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
638 if( !szwName )
639 goto end;
640 MultiByteToWideChar( CP_ACP, 0, szName, -1, szwName, len );
642 len = MultiByteToWideChar( CP_ACP, 0, szValue, -1, NULL, 0 );
643 szwValue = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
644 if( !szwValue)
645 goto end;
646 MultiByteToWideChar( CP_ACP, 0, szValue , -1, szwValue, len );
648 hr = MsiSetPropertyW( hInstall, szwName, szwValue);
650 end:
651 HeapFree( GetProcessHeap(), 0, szwName );
652 HeapFree( GetProcessHeap(), 0, szwValue );
654 return hr;
657 UINT MSI_SetPropertyW( MSIPACKAGE *package, LPCWSTR szName, LPCWSTR szValue)
659 MSIQUERY *view;
660 MSIRECORD *row;
661 UINT rc;
662 DWORD sz = 0;
663 static const WCHAR Insert[]=
664 {'I','N','S','E','R','T',' ','i','n','t','o',' ','`','_','P','r','o','p'
665 ,'e','r','t','y','`',' ','(','`','_','P','r','o','p','e','r','t','y','`'
666 ,',','`','V','a','l','u','e','`',')',' ','V','A','L','U','E','S'
667 ,' ','(','?',')',0};
668 static const WCHAR Update[]=
669 {'U','P','D','A','T','E',' ','_','P','r','o','p','e'
670 ,'r','t','y',' ','s','e','t',' ','`','V','a','l','u','e','`',' ','='
671 ,' ','?',' ','w','h','e','r','e',' ','`','_','P','r','o','p'
672 ,'e','r','t','y','`',' ','=',' ','\'','%','s','\'',0};
673 WCHAR Query[1024];
675 TRACE("Setting property (%s %s)\n",debugstr_w(szName),
676 debugstr_w(szValue));
678 rc = MSI_GetPropertyW(package,szName,0,&sz);
679 if (rc==ERROR_MORE_DATA || rc == ERROR_SUCCESS)
681 sprintfW(Query,Update,szName);
683 row = MSI_CreateRecord(1);
684 MSI_RecordSetStringW(row,1,szValue);
687 else
689 strcpyW(Query,Insert);
691 row = MSI_CreateRecord(2);
692 MSI_RecordSetStringW(row,1,szName);
693 MSI_RecordSetStringW(row,2,szValue);
697 rc = MSI_DatabaseOpenViewW(package->db,Query,&view);
698 if (rc!= ERROR_SUCCESS)
700 msiobj_release(&row->hdr);
701 return rc;
704 rc = MSI_ViewExecute(view,row);
706 msiobj_release(&row->hdr);
707 MSI_ViewClose(view);
708 msiobj_release(&view->hdr);
710 return rc;
713 UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue)
715 MSIPACKAGE *package;
716 UINT ret;
718 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
719 if( !package)
720 return ERROR_INVALID_HANDLE;
721 ret = MSI_SetPropertyW( package, szName, szValue);
722 msiobj_release( &package->hdr );
723 return ret;
726 static UINT MSI_GetPropertyRow(MSIPACKAGE *package, LPCWSTR szName, MSIRECORD **row)
728 MSIQUERY *view;
729 UINT rc, sz;
730 static const WCHAR select[]=
731 {'s','e','l','e','c','t',' ','V','a','l','u','e',' ','f','r','o','m',' '
732 ,'_','P','r','o','p','e','r','t','y',' ','w','h','e','r','e',' '
733 ,'_','P','r','o','p','e','r','t','y','=','`','%','s','`',0};
734 LPWSTR query;
736 if (!szName)
737 return ERROR_INVALID_PARAMETER;
739 sz = sizeof select + strlenW(szName)*sizeof(WCHAR);
740 query = HeapAlloc(GetProcessHeap(), 0, sz);
741 sprintfW(query,select,szName);
743 rc = MSI_DatabaseOpenViewW(package->db, query, &view);
744 HeapFree(GetProcessHeap(), 0, query);
745 if (rc == ERROR_SUCCESS)
747 rc = MSI_ViewExecute(view, 0);
748 if (rc == ERROR_SUCCESS)
749 rc = MSI_ViewFetch(view,row);
751 MSI_ViewClose(view);
752 msiobj_release(&view->hdr);
755 return rc;
758 UINT MSI_GetPropertyW(MSIPACKAGE *package, LPCWSTR szName,
759 LPWSTR szValueBuf, DWORD* pchValueBuf)
761 MSIRECORD *row;
762 UINT rc;
764 rc = MSI_GetPropertyRow(package, szName, &row);
766 if (*pchValueBuf > 0)
767 szValueBuf[0] = 0;
769 if (rc == ERROR_SUCCESS)
771 rc = MSI_RecordGetStringW(row,1,szValueBuf,pchValueBuf);
772 msiobj_release(&row->hdr);
775 if (rc == ERROR_SUCCESS)
776 TRACE("returning %s for property %s\n", debugstr_w(szValueBuf),
777 debugstr_w(szName));
778 else if (rc == ERROR_MORE_DATA)
779 TRACE("need %li sized buffer for %s\n", *pchValueBuf,
780 debugstr_w(szName));
781 else
783 *pchValueBuf = 0;
784 TRACE("property not found\n");
787 return rc;
790 UINT MSI_GetPropertyA(MSIPACKAGE *package, LPCSTR szName,
791 LPSTR szValueBuf, DWORD* pchValueBuf)
793 MSIRECORD *row;
794 UINT rc, len;
795 LPWSTR szwName;
797 if (*pchValueBuf > 0)
798 szValueBuf[0] = 0;
800 len = MultiByteToWideChar( CP_ACP, 0, szName, -1, NULL, 0 );
801 szwName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
802 if (!szwName)
803 return ERROR_NOT_ENOUGH_MEMORY;
804 MultiByteToWideChar( CP_ACP, 0, szName, -1, szwName, len );
806 rc = MSI_GetPropertyRow(package, szwName, &row);
807 if (rc == ERROR_SUCCESS)
809 rc = MSI_RecordGetStringA(row,1,szValueBuf,pchValueBuf);
810 msiobj_release(&row->hdr);
813 if (rc == ERROR_SUCCESS)
814 TRACE("returning %s for property %s\n", debugstr_a(szValueBuf),
815 debugstr_a(szName));
816 else if (rc == ERROR_MORE_DATA)
817 TRACE("need %ld sized buffer for %s\n", *pchValueBuf,
818 debugstr_a(szName));
819 else
821 *pchValueBuf = 0;
822 TRACE("property not found\n");
824 HeapFree( GetProcessHeap(), 0, szwName );
826 return rc;
829 UINT WINAPI MsiGetPropertyA(MSIHANDLE hInstall, LPCSTR szName, LPSTR szValueBuf, DWORD* pchValueBuf)
831 MSIPACKAGE *package;
832 UINT ret;
834 TRACE("%lu %s %lu\n", hInstall, debugstr_a(szName), *pchValueBuf);
836 if (0 == hInstall)
837 return ERROR_INVALID_HANDLE;
838 if (NULL == szName)
839 return ERROR_INVALID_PARAMETER;
840 if (NULL != szValueBuf && NULL == pchValueBuf)
841 return ERROR_INVALID_PARAMETER;
843 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
844 if (!package)
845 return ERROR_INVALID_HANDLE;
846 ret = MSI_GetPropertyA(package, szName, szValueBuf, pchValueBuf );
847 msiobj_release( &package->hdr );
848 return ret;
852 UINT WINAPI MsiGetPropertyW(MSIHANDLE hInstall, LPCWSTR szName,
853 LPWSTR szValueBuf, DWORD* pchValueBuf)
855 MSIPACKAGE *package;
856 UINT ret;
858 if (0 == hInstall)
859 return ERROR_INVALID_HANDLE;
860 if (NULL == szName)
861 return ERROR_INVALID_PARAMETER;
862 if (NULL != szValueBuf && NULL == pchValueBuf)
863 return ERROR_INVALID_PARAMETER;
865 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
866 if (!package)
867 return ERROR_INVALID_HANDLE;
868 ret = MSI_GetPropertyW(package, szName, szValueBuf, pchValueBuf );
869 msiobj_release( &package->hdr );
870 return ret;