Prevent garbage being passed for windows directory.
[wine/multimedia.git] / dlls / msi / package.c
blob3774f98380c636e7b9c4745e4842a739e82c8cf3
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);
57 if (package->features && package->loaded_features > 0)
58 HeapFree(GetProcessHeap(),0,package->features);
60 if (package->folders && package->loaded_folders > 0)
61 HeapFree(GetProcessHeap(),0,package->folders);
63 if (package->components && package->loaded_components > 0)
64 HeapFree(GetProcessHeap(),0,package->components);
66 if (package->files && package->loaded_files > 0)
67 HeapFree(GetProcessHeap(),0,package->files);
68 msiobj_release( &package->db->hdr );
71 UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
73 LPWSTR szwPack = NULL;
74 UINT len, ret;
76 TRACE("%s %p\n",debugstr_a(szPackage), phPackage);
78 if( szPackage )
80 len = MultiByteToWideChar( CP_ACP, 0, szPackage, -1, NULL, 0 );
81 szwPack = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
82 if( szwPack )
83 MultiByteToWideChar( CP_ACP, 0, szPackage, -1, szwPack, len );
86 ret = MsiOpenPackageW( szwPack, phPackage );
88 if( szwPack )
89 HeapFree( GetProcessHeap(), 0, szwPack );
91 return ret;
95 static const UINT clone_properties(MSIDATABASE *db)
97 MSIQUERY * view = NULL;
98 UINT rc;
99 static const WCHAR CreateSql[] = {
100 'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','_','P','r','o',
101 'p','e','r','t','y','`',' ','(',' ','`','_','P','r','o','p','e','r','t',
102 'y','`',' ','C','H','A','R','(','5','6',')',' ','N','O','T',' ','N','U',
103 'L','L',',',' ','`','V','a','l','u','e','`',' ','C','H','A','R','(','9',
104 '8',')',' ','N','O','T',' ','N','U','L','L',' ','P','R','I','M','A','R',
105 'Y',' ','K','E','Y',' ','`','_','P','r','o','p','e','r','t','y','`',')',0};
106 static const WCHAR Query[] = {
107 'S','E','L','E','C','T',' ','*',' ',
108 'f','r','o','m',' ','P','r','o','p','e','r','t','y',0};
109 static const WCHAR Insert[] = {
110 'I','N','S','E','R','T',' ','i','n','t','o',' ',
111 '`','_','P','r','o','p','e','r','t','y','`',' ',
112 '(','`','_','P','r','o','p','e','r','t','y','`',',',
113 '`','V','a','l','u','e','`',')',' ',
114 'V','A','L','U','E','S',' ','(','?',')',0};
116 /* create the temporary properties table */
117 rc = MSI_DatabaseOpenViewW(db, CreateSql, &view);
118 if (rc != ERROR_SUCCESS)
119 return rc;
120 rc = MSI_ViewExecute(view,0);
121 MSI_ViewClose(view);
122 msiobj_release(&view->hdr);
123 if (rc != ERROR_SUCCESS)
124 return rc;
126 /* clone the existing properties */
127 rc = MSI_DatabaseOpenViewW(db, Query, &view);
128 if (rc != ERROR_SUCCESS)
129 return rc;
131 rc = MSI_ViewExecute(view, 0);
132 if (rc != ERROR_SUCCESS)
134 MSI_ViewClose(view);
135 msiobj_release(&view->hdr);
136 return rc;
138 while (1)
140 MSIRECORD * row;
141 MSIQUERY * view2;
143 rc = MSI_ViewFetch(view,&row);
144 if (rc != ERROR_SUCCESS)
145 break;
147 rc = MSI_DatabaseOpenViewW(db,Insert,&view2);
148 if (rc!= ERROR_SUCCESS)
149 continue;
150 rc = MSI_ViewExecute(view2,row);
151 MSI_ViewClose(view2);
152 msiobj_release(&view2->hdr);
154 if (rc == ERROR_SUCCESS)
155 msiobj_release(&row->hdr);
157 MSI_ViewClose(view);
158 msiobj_release(&view->hdr);
160 return rc;
164 * There are a whole slew of these we need to set
167 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/properties.asp
169 static VOID set_installer_properties(MSIPACKAGE *package)
171 WCHAR pth[MAX_PATH];
172 OSVERSIONINFOA OSVersion;
173 DWORD verval;
174 WCHAR verstr[10];
176 static const WCHAR cszbs[]={'\\',0};
177 static const WCHAR CFF[] =
178 {'C','o','m','m','o','n','F','i','l','e','s','F','o','l','d','e','r',0};
179 static const WCHAR PFF[] =
180 {'P','r','o','g','r','a','m','F','i','l','e','s','F','o','l','d','e','r',0};
181 static const WCHAR CADF[] =
182 {'C','o','m','m','o','n','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
183 static const WCHAR ATF[] =
184 {'A','d','m','i','n','T','o','o','l','s','F','o','l','d','e','r',0};
185 static const WCHAR ADF[] =
186 {'A','p','p','D','a','t','a','F','o','l','d','e','r',0};
187 static const WCHAR SF[] =
188 {'S','y','s','t','e','m','F','o','l','d','e','r',0};
189 static const WCHAR LADF[] =
190 {'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
191 static const WCHAR MPF[] =
192 {'M','y','P','i','c','t','u','r','e','s','F','o','l','d','e','r',0};
193 static const WCHAR PF[] =
194 {'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0};
195 static const WCHAR WF[] =
196 {'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
197 static const WCHAR TF[]=
198 {'T','e','m','p','F','o','l','d','e','r',0};
199 static const WCHAR szAdminUser[] =
200 {'A','d','m','i','n','U','s','e','r',0};
201 static const WCHAR szPriv[] =
202 {'P','r','i','v','i','l','e','g','e','d',0};
203 static const WCHAR szOne[] =
204 {'1',0};
205 static const WCHAR v9x[] = { 'V','e','r','s','i','o','n','9','X',0 };
206 static const WCHAR vNT[] = { 'V','e','r','s','i','o','n','N','T',0 };
207 static const WCHAR szFormat[] = {'%','l','i',0};
208 static const WCHAR szWinBuild[] =
209 {'W','i','n','d','o','w','s','B','u','i','l','d', 0 };
210 static const WCHAR szSPL[] =
211 {'S','e','r','v','i','c','e','P','a','c','k','L','e','v','e','l',0 };
212 static const WCHAR szSix[] = {'6',0 };
214 /* these need to be dynamically descovered sometime */
216 static const WCHAR ProgramMenuFolder[] =
217 {'P','r','o','g','r','a','m','M','e','n','u','F','o','l','d','e','r',0};
218 static const WCHAR PMFPath[] =
219 {'C',':','\\','W','i','n','d','o','w','s','\\','S','t','a','r','t',' ',
220 'M','e','n','u','\\','P','r','o','g','r','a','m','s','\\',0};
221 static const WCHAR FavoritesFolder[] =
222 {'F','a','v','o','r','i','t','e','s','F','o','l','d','e','r',0};
223 static const WCHAR FFPath[] =
224 {'C',':','\\','W','i','n','d','o','w','s','\\',
225 'F','a','v','o','r','i','t','e','s','\\',0};
226 static const WCHAR FontsFolder[] =
227 {'F','o','n','t','s','F','o','l','d','e','r',0};
228 static const WCHAR FoFPath[] =
229 {'C',':','\\','W','i','n','d','o','w','s','\\','F','o','n','t','s','\\',0};
230 static const WCHAR SendToFolder[] =
231 {'S','e','n','d','T','o','F','o','l','d','e','r',0};
232 static const WCHAR STFPath[] =
233 {'C',':','\\','W','i','n','d','o','w','s','\\','S','e','n','d','T','o','\\',0};
234 static const WCHAR StartMenuFolder[] =
235 {'S','t','a','r','t','M','e','n','u','F','o','l','d','e','r',0};
236 static const WCHAR SMFPath[] =
237 {'C',':','\\','W','i','n','d','o','w','s','\\','S','t','a','r','t',' ',
238 'M','e','n','u','\\',0};
239 static const WCHAR StartupFolder[] =
240 {'S','t','a','r','t','u','p','F','o','l','d','e','r',0};
241 static const WCHAR SFPath[] =
242 {'C',':','\\','W','i','n','d','o','w','s','\\','S','t','a','r','t',' ',
243 'M','e','n','u','\\','P','r','o','g','r','a','m','s','\\',
244 'S','t','a','r','t','u','p','\\',0};
245 static const WCHAR TemplateFolder[] =
246 {'T','e','m','p','l','a','t','e','F','o','l','d','e','r',0};
247 static const WCHAR TFPath[] =
248 {'C',':','\\','W','i','n','d','o','w','s','\\',
249 'S','h','e','l','l','N','e','w','\\',0};
250 static const WCHAR DesktopFolder[] =
251 {'D','e','s','k','t','o','p','F','o','l','d','e','r',0};
252 static const WCHAR DFPath[] =
253 {'C',':','\\','W','i','n','d','o','w','s','\\',
254 'D','e','s','k','t','o','p','\\',0};
257 * Other things I notice set
259 ScreenY
260 ScreenX
261 SystemLanguageID
262 ComputerName
263 UserLanguageID
264 LogonUser
265 VirtualMemory
266 PhysicalMemory
267 Intel
268 ShellAdvSupport
269 DefaultUIFont
270 VersionMsi
271 VersionDatabase
272 PackagecodeChanging
273 ProductState
274 CaptionHeight
275 BorderTop
276 BorderSide
277 TextHeight
278 ColorBits
279 RedirectedDllSupport
280 Time
281 Date
282 Privilaged
285 SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES_COMMON,NULL,0,pth);
286 strcatW(pth,cszbs);
287 MSI_SetPropertyW(package, CFF, pth);
289 SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES,NULL,0,pth);
290 strcatW(pth,cszbs);
291 MSI_SetPropertyW(package, PFF, pth);
293 SHGetFolderPathW(NULL,CSIDL_COMMON_APPDATA,NULL,0,pth);
294 strcatW(pth,cszbs);
295 MSI_SetPropertyW(package, CADF, pth);
297 SHGetFolderPathW(NULL,CSIDL_ADMINTOOLS,NULL,0,pth);
298 strcatW(pth,cszbs);
299 MSI_SetPropertyW(package, ATF, pth);
301 SHGetFolderPathW(NULL,CSIDL_APPDATA,NULL,0,pth);
302 strcatW(pth,cszbs);
303 MSI_SetPropertyW(package, ADF, pth);
305 SHGetFolderPathW(NULL,CSIDL_SYSTEM,NULL,0,pth);
306 strcatW(pth,cszbs);
307 MSI_SetPropertyW(package, SF, pth);
309 SHGetFolderPathW(NULL,CSIDL_LOCAL_APPDATA,NULL,0,pth);
310 strcatW(pth,cszbs);
311 MSI_SetPropertyW(package, LADF, pth);
313 SHGetFolderPathW(NULL,CSIDL_MYPICTURES,NULL,0,pth);
314 strcatW(pth,cszbs);
315 MSI_SetPropertyW(package, MPF, pth);
317 SHGetFolderPathW(NULL,CSIDL_PERSONAL,NULL,0,pth);
318 strcatW(pth,cszbs);
319 MSI_SetPropertyW(package, PF, pth);
321 SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
322 strcatW(pth,cszbs);
323 MSI_SetPropertyW(package, WF, pth);
325 GetTempPathW(MAX_PATH,pth);
326 MSI_SetPropertyW(package, TF, pth);
329 /* in a wine environment the user is always admin and privileged */
330 MSI_SetPropertyW(package,szAdminUser,szOne);
331 MSI_SetPropertyW(package,szPriv,szOne);
333 /* set the os things */
334 OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
335 GetVersionExA(&OSVersion);
336 verval = OSVersion.dwMinorVersion+OSVersion.dwMajorVersion*100;
337 sprintfW(verstr,szFormat,verval);
338 switch (OSVersion.dwPlatformId)
340 case VER_PLATFORM_WIN32_WINDOWS:
341 MSI_SetPropertyW(package,v9x,verstr);
342 break;
343 case VER_PLATFORM_WIN32_NT:
344 MSI_SetPropertyW(package,vNT,verstr);
345 break;
347 sprintfW(verstr,szFormat,OSVersion.dwBuildNumber);
348 MSI_SetPropertyW(package,szWinBuild,verstr);
349 /* just fudge this */
350 MSI_SetPropertyW(package,szSPL,szSix);
352 /* FIXME: these need to be set properly */
354 MSI_SetPropertyW(package,ProgramMenuFolder,PMFPath);
355 MSI_SetPropertyW(package,FavoritesFolder,FFPath);
356 MSI_SetPropertyW(package,FontsFolder,FoFPath);
357 MSI_SetPropertyW(package,SendToFolder,STFPath);
358 MSI_SetPropertyW(package,StartMenuFolder,SMFPath);
359 MSI_SetPropertyW(package,StartupFolder,SFPath);
360 MSI_SetPropertyW(package,TemplateFolder,TFPath);
361 MSI_SetPropertyW(package,DesktopFolder,DFPath);
364 UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
366 UINT rc;
367 MSIDATABASE *db = NULL;
368 MSIPACKAGE *package = NULL;
369 WCHAR uilevel[10];
370 UINT ret = ERROR_FUNCTION_FAILED;
372 static const WCHAR OriginalDatabase[] =
373 {'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
374 static const WCHAR Database[] =
375 {'D','A','T','A','B','A','S','E',0};
376 static const WCHAR szpi[] = {'%','i',0};
377 static const WCHAR szLevel[] = { 'U','I','L','e','v','e','l',0 };
379 TRACE("%s %p\n",debugstr_w(szPackage), pPackage);
381 if (szPackage[0] == '#')
383 INT handle = atoiW(&szPackage[1]);
384 db = msihandle2msiinfo( handle , MSIHANDLETYPE_DATABASE);
386 else
388 rc = MSI_OpenDatabaseW(szPackage, MSIDBOPEN_READONLY, &db);
389 if (rc != ERROR_SUCCESS)
390 return ERROR_FUNCTION_FAILED;
393 package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE),
394 MSI_FreePackage );
396 if (package)
398 msiobj_addref( &db->hdr );
400 package->db = db;
401 package->features = NULL;
402 package->folders = NULL;
403 package->components = NULL;
404 package->files = NULL;
405 package->loaded_features = 0;
406 package->loaded_folders = 0;
407 package->loaded_components= 0;
408 package->loaded_files = 0;
410 /* OK, here is where we do a slew of things to the database to
411 * prep for all that is to come as a package */
413 clone_properties(db);
414 set_installer_properties(package);
415 MSI_SetPropertyW(package, OriginalDatabase, szPackage);
416 MSI_SetPropertyW(package, Database, szPackage);
417 sprintfW(uilevel,szpi,gUILevel);
418 MSI_SetPropertyW(package, szLevel, uilevel);
420 msiobj_addref( &package->hdr );
421 *pPackage = package;
422 ret = ERROR_SUCCESS;
425 if( package )
426 msiobj_release( &package->hdr );
427 if( db )
428 msiobj_release( &db->hdr );
430 return ret;
433 UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
435 MSIPACKAGE *package = NULL;
436 UINT ret;
438 ret = MSI_OpenPackageW( szPackage, &package);
439 if( ret == ERROR_SUCCESS )
441 *phPackage = alloc_msihandle( &package->hdr );
442 msiobj_release( &package->hdr );
444 return ret;
447 UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
449 FIXME("%s 0x%08lx %p\n",debugstr_a(szPackage), dwOptions, phPackage);
450 return ERROR_CALL_NOT_IMPLEMENTED;
453 UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
455 FIXME("%s 0x%08lx %p\n",debugstr_w(szPackage), dwOptions, phPackage);
456 return ERROR_CALL_NOT_IMPLEMENTED;
459 MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
461 MSIPACKAGE *package;
462 MSIHANDLE handle = 0;
464 TRACE("(%ld)\n",hInstall);
466 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
467 if( package)
469 handle = alloc_msihandle( &package->db->hdr );
470 msiobj_release( &package->hdr );
473 return handle;
476 INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType,
477 MSIRECORD *record)
479 DWORD log_type = 0;
480 LPWSTR message;
481 DWORD sz;
482 DWORD total_size = 0;
483 INT msg_field=1;
484 INT i;
485 INT rc;
486 char *msg;
487 int len;
489 TRACE("%x \n",eMessageType);
490 rc = 0;
492 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ERROR)
493 log_type |= INSTALLLOGMODE_ERROR;
494 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_WARNING)
495 log_type |= INSTALLLOGMODE_WARNING;
496 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_USER)
497 log_type |= INSTALLLOGMODE_USER;
498 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INFO)
499 log_type |= INSTALLLOGMODE_INFO;
500 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA)
501 log_type |= INSTALLLOGMODE_COMMONDATA;
502 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART)
503 log_type |= INSTALLLOGMODE_ACTIONSTART;
504 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONDATA)
505 log_type |= INSTALLLOGMODE_ACTIONDATA;
506 /* just a guess */
507 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_PROGRESS)
508 log_type |= 0x800;
510 message = HeapAlloc(GetProcessHeap(),0,1*sizeof (WCHAR));
511 message[0]=0;
512 msg_field = MSI_RecordGetFieldCount(record);
513 for (i = 1; i <= msg_field; i++)
515 LPWSTR tmp;
516 WCHAR number[3];
517 const static WCHAR format[] = { '%','i',':',' ',0};
518 const static WCHAR space[] = { ' ',0};
519 sz = 0;
520 MSI_RecordGetStringW(record,i,NULL,&sz);
521 sz+=4;
522 total_size+=sz*sizeof(WCHAR);
523 tmp = HeapAlloc(GetProcessHeap(),0,sz*sizeof(WCHAR));
524 message = HeapReAlloc(GetProcessHeap(),0,message,total_size*sizeof (WCHAR));
526 MSI_RecordGetStringW(record,i,tmp,&sz);
528 if (msg_field > 1)
530 sprintfW(number,format,i);
531 strcatW(message,number);
533 strcatW(message,tmp);
534 if (msg_field > 1)
535 strcatW(message,space);
537 HeapFree(GetProcessHeap(),0,tmp);
540 TRACE("(%p %lx %lx %s)\n",gUIHandler, gUIFilter, log_type,
541 debugstr_w(message));
543 /* convert it to ASCII */
544 len = WideCharToMultiByte( CP_ACP, 0, message, -1,
545 NULL, 0, NULL, NULL );
546 msg = HeapAlloc( GetProcessHeap(), 0, len );
547 WideCharToMultiByte( CP_ACP, 0, message, -1,
548 msg, len, NULL, NULL );
550 if (gUIHandler && (gUIFilter & log_type))
552 rc = gUIHandler(gUIContext,eMessageType,msg);
555 if ((!rc) && (gszLogFile[0]) && !((eMessageType & 0xff000000) ==
556 INSTALLMESSAGE_PROGRESS))
558 DWORD write;
559 HANDLE log_file = CreateFileW(gszLogFile,GENERIC_WRITE, 0, NULL,
560 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
562 if (log_file != INVALID_HANDLE_VALUE)
564 SetFilePointer(log_file,0, NULL, FILE_END);
565 WriteFile(log_file,msg,strlen(msg),&write,NULL);
566 WriteFile(log_file,"\n",1,&write,NULL);
567 CloseHandle(log_file);
570 HeapFree( GetProcessHeap(), 0, msg );
572 HeapFree(GetProcessHeap(),0,message);
573 return ERROR_SUCCESS;
576 INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
577 MSIHANDLE hRecord)
579 UINT ret = ERROR_INVALID_HANDLE;
580 MSIPACKAGE *package = NULL;
581 MSIRECORD *record = NULL;
583 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
584 if( !package )
585 goto out;
587 record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD );
588 if( !record )
589 goto out;
591 ret = MSI_ProcessMessage( package, eMessageType, record );
593 out:
594 if( package )
595 msiobj_release( &package->hdr );
596 if( record )
597 msiobj_release( &record->hdr );
599 return ret;
602 /* property code */
603 UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue)
605 LPWSTR szwName = NULL, szwValue = NULL;
606 UINT hr = ERROR_INSTALL_FAILURE;
607 UINT len;
609 if (0 == hInstall) {
610 return ERROR_INVALID_HANDLE;
612 if (NULL == szName) {
613 return ERROR_INVALID_PARAMETER;
615 if (NULL == szValue) {
616 return ERROR_INVALID_PARAMETER;
619 len = MultiByteToWideChar( CP_ACP, 0, szName, -1, NULL, 0 );
620 szwName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
621 if( !szwName )
622 goto end;
623 MultiByteToWideChar( CP_ACP, 0, szName, -1, szwName, len );
625 len = MultiByteToWideChar( CP_ACP, 0, szValue, -1, NULL, 0 );
626 szwValue = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
627 if( !szwValue)
628 goto end;
629 MultiByteToWideChar( CP_ACP, 0, szValue , -1, szwValue, len );
631 hr = MsiSetPropertyW( hInstall, szwName, szwValue);
633 end:
634 if( szwName )
635 HeapFree( GetProcessHeap(), 0, szwName );
636 if( szwValue )
637 HeapFree( GetProcessHeap(), 0, szwValue );
639 return hr;
642 UINT MSI_SetPropertyW( MSIPACKAGE *package, LPCWSTR szName, LPCWSTR szValue)
644 MSIQUERY *view;
645 MSIRECORD *row;
646 UINT rc;
647 DWORD sz = 0;
648 static const WCHAR Insert[]=
649 {'I','N','S','E','R','T',' ','i','n','t','o',' ','`','_','P','r','o','p'
650 ,'e','r','t','y','`',' ','(','`','_','P','r','o','p','e','r','t','y','`'
651 ,',','`','V','a','l','u','e','`',')',' ','V','A','L','U','E','S'
652 ,' ','(','?',')',0};
653 static const WCHAR Update[]=
654 {'U','P','D','A','T','E',' ','_','P','r','o','p','e'
655 ,'r','t','y',' ','s','e','t',' ','`','V','a','l','u','e','`',' ','='
656 ,' ','?',' ','w','h','e','r','e',' ','`','_','P','r','o','p'
657 ,'e','r','t','y','`',' ','=',' ','\'','%','s','\'',0};
658 WCHAR Query[1024];
660 TRACE("Setting property (%s %s)\n",debugstr_w(szName),
661 debugstr_w(szValue));
663 rc = MSI_GetPropertyW(package,szName,0,&sz);
664 if (rc==ERROR_MORE_DATA || rc == ERROR_SUCCESS)
666 sprintfW(Query,Update,szName);
668 row = MSI_CreateRecord(1);
669 MSI_RecordSetStringW(row,1,szValue);
672 else
674 strcpyW(Query,Insert);
676 row = MSI_CreateRecord(2);
677 MSI_RecordSetStringW(row,1,szName);
678 MSI_RecordSetStringW(row,2,szValue);
682 rc = MSI_DatabaseOpenViewW(package->db,Query,&view);
683 if (rc!= ERROR_SUCCESS)
685 msiobj_release(&row->hdr);
686 return rc;
689 rc = MSI_ViewExecute(view,row);
691 msiobj_release(&row->hdr);
692 MSI_ViewClose(view);
693 msiobj_release(&view->hdr);
695 return rc;
698 UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue)
700 MSIPACKAGE *package;
701 UINT ret;
703 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
704 if( !package)
705 return ERROR_INVALID_HANDLE;
706 ret = MSI_SetPropertyW( package, szName, szValue);
707 msiobj_release( &package->hdr );
708 return ret;
711 UINT WINAPI MsiGetPropertyA(MSIHANDLE hInstall, LPCSTR szName, LPSTR szValueBuf, DWORD* pchValueBuf)
713 LPWSTR szwName = NULL, szwValueBuf = NULL;
714 UINT hr = ERROR_INSTALL_FAILURE;
716 if (0 == hInstall) {
717 return ERROR_INVALID_HANDLE;
719 if (NULL == szName) {
720 return ERROR_INVALID_PARAMETER;
723 TRACE("%lu %s %lu\n", hInstall, debugstr_a(szName), *pchValueBuf);
725 if (NULL != szValueBuf && NULL == pchValueBuf) {
726 return ERROR_INVALID_PARAMETER;
728 if( szName )
730 UINT len = MultiByteToWideChar( CP_ACP, 0, szName, -1, NULL, 0 );
731 szwName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
732 if( !szwName )
733 goto end;
734 MultiByteToWideChar( CP_ACP, 0, szName, -1, szwName, len );
735 } else {
736 return ERROR_INVALID_PARAMETER;
738 if( szValueBuf )
740 szwValueBuf = HeapAlloc( GetProcessHeap(), 0, (*pchValueBuf) * sizeof(WCHAR) );
741 if( !szwValueBuf )
742 goto end;
745 if( *pchValueBuf > 0 )
747 /* be sure to blank the string first */
748 szValueBuf[0]=0;
751 hr = MsiGetPropertyW( hInstall, szwName, szwValueBuf, pchValueBuf );
753 if( *pchValueBuf > 0 )
755 WideCharToMultiByte(CP_ACP, 0, szwValueBuf, -1, szValueBuf, *pchValueBuf, NULL, NULL);
758 end:
759 if( szwName )
760 HeapFree( GetProcessHeap(), 0, szwName );
761 if( szwValueBuf )
762 HeapFree( GetProcessHeap(), 0, szwValueBuf );
764 return hr;
767 UINT MSI_GetPropertyW(MSIPACKAGE *package, LPCWSTR szName,
768 LPWSTR szValueBuf, DWORD* pchValueBuf)
770 MSIQUERY *view;
771 MSIRECORD *row;
772 UINT rc;
773 WCHAR Query[1024]=
774 {'s','e','l','e','c','t',' ','V','a','l','u','e',' ','f','r','o','m',' '
775 ,'_','P','r','o','p','e','r','t','y',' ','w','h','e','r','e',' '
776 ,'_','P','r','o','p','e','r','t','y','=','`',0};
778 static const WCHAR szEnd[]={'`',0};
780 if (NULL == szName) {
781 return ERROR_INVALID_PARAMETER;
784 strcatW(Query,szName);
785 strcatW(Query,szEnd);
787 rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
788 if (rc == ERROR_SUCCESS)
790 DWORD sz;
791 WCHAR value[0x100];
793 /* even on unsuccessful lookup native msi blanks this string */
794 if (*pchValueBuf > 0)
795 szValueBuf[0] = 0;
797 rc = MSI_ViewExecute(view, 0);
798 if (rc != ERROR_SUCCESS)
800 MSI_ViewClose(view);
801 msiobj_release(&view->hdr);
802 return rc;
805 rc = MSI_ViewFetch(view,&row);
806 if (rc == ERROR_SUCCESS)
808 sz=0x100;
809 rc = MSI_RecordGetStringW(row,1,value,&sz);
810 strncpyW(szValueBuf,value,min(sz+1,*pchValueBuf));
811 *pchValueBuf = sz+1;
812 msiobj_release(&row->hdr);
814 MSI_ViewClose(view);
815 msiobj_release(&view->hdr);
818 if (rc == ERROR_SUCCESS)
819 TRACE("returning %s for property %s\n", debugstr_w(szValueBuf),
820 debugstr_w(szName));
821 else
823 *pchValueBuf = 0;
824 TRACE("property not found\n");
827 return rc;
831 UINT WINAPI MsiGetPropertyW(MSIHANDLE hInstall, LPCWSTR szName,
832 LPWSTR szValueBuf, DWORD* pchValueBuf)
834 MSIPACKAGE *package;
835 UINT ret;
837 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
838 if( !package)
839 return ERROR_INVALID_HANDLE;
840 ret = MSI_GetPropertyW(package, szName, szValueBuf, pchValueBuf );
841 msiobj_release( &package->hdr );
842 return ret;