Fix string length return from HttpQueryInfoA.
[wine/multimedia.git] / dlls / msi / package.c
blob0f74e165ea1b3f811205fc39d2a4a1897a707e0d
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], msiver[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 static const WCHAR szVersionMsi[] = { 'V','e','r','s','i','o','n','M','s','i',0 };
215 static const WCHAR szFormat2[] = {'%','l','i','.','%','l','i',0};
217 /* these need to be dynamically discovered sometime */
219 static const WCHAR ProgramMenuFolder[] =
220 {'P','r','o','g','r','a','m','M','e','n','u','F','o','l','d','e','r',0};
221 static const WCHAR PMFPath[] =
222 {'C',':','\\','W','i','n','d','o','w','s','\\','S','t','a','r','t',' ',
223 'M','e','n','u','\\','P','r','o','g','r','a','m','s','\\',0};
224 static const WCHAR FavoritesFolder[] =
225 {'F','a','v','o','r','i','t','e','s','F','o','l','d','e','r',0};
226 static const WCHAR FFPath[] =
227 {'C',':','\\','W','i','n','d','o','w','s','\\',
228 'F','a','v','o','r','i','t','e','s','\\',0};
229 static const WCHAR FontsFolder[] =
230 {'F','o','n','t','s','F','o','l','d','e','r',0};
231 static const WCHAR FoFPath[] =
232 {'C',':','\\','W','i','n','d','o','w','s','\\','F','o','n','t','s','\\',0};
233 static const WCHAR SendToFolder[] =
234 {'S','e','n','d','T','o','F','o','l','d','e','r',0};
235 static const WCHAR STFPath[] =
236 {'C',':','\\','W','i','n','d','o','w','s','\\','S','e','n','d','T','o','\\',0};
237 static const WCHAR StartMenuFolder[] =
238 {'S','t','a','r','t','M','e','n','u','F','o','l','d','e','r',0};
239 static const WCHAR SMFPath[] =
240 {'C',':','\\','W','i','n','d','o','w','s','\\','S','t','a','r','t',' ',
241 'M','e','n','u','\\',0};
242 static const WCHAR StartupFolder[] =
243 {'S','t','a','r','t','u','p','F','o','l','d','e','r',0};
244 static const WCHAR SFPath[] =
245 {'C',':','\\','W','i','n','d','o','w','s','\\','S','t','a','r','t',' ',
246 'M','e','n','u','\\','P','r','o','g','r','a','m','s','\\',
247 'S','t','a','r','t','u','p','\\',0};
248 static const WCHAR TemplateFolder[] =
249 {'T','e','m','p','l','a','t','e','F','o','l','d','e','r',0};
250 static const WCHAR TFPath[] =
251 {'C',':','\\','W','i','n','d','o','w','s','\\',
252 'S','h','e','l','l','N','e','w','\\',0};
253 static const WCHAR DesktopFolder[] =
254 {'D','e','s','k','t','o','p','F','o','l','d','e','r',0};
255 static const WCHAR DFPath[] =
256 {'C',':','\\','W','i','n','d','o','w','s','\\',
257 'D','e','s','k','t','o','p','\\',0};
260 * Other things I notice set
262 ScreenY
263 ScreenX
264 SystemLanguageID
265 ComputerName
266 UserLanguageID
267 LogonUser
268 VirtualMemory
269 PhysicalMemory
270 Intel
271 ShellAdvSupport
272 DefaultUIFont
273 VersionDatabase
274 PackagecodeChanging
275 ProductState
276 CaptionHeight
277 BorderTop
278 BorderSide
279 TextHeight
280 ColorBits
281 RedirectedDllSupport
282 Time
283 Date
284 Privileged
287 SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES_COMMON,NULL,0,pth);
288 strcatW(pth,cszbs);
289 MSI_SetPropertyW(package, CFF, pth);
291 SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES,NULL,0,pth);
292 strcatW(pth,cszbs);
293 MSI_SetPropertyW(package, PFF, pth);
295 SHGetFolderPathW(NULL,CSIDL_COMMON_APPDATA,NULL,0,pth);
296 strcatW(pth,cszbs);
297 MSI_SetPropertyW(package, CADF, pth);
299 SHGetFolderPathW(NULL,CSIDL_ADMINTOOLS,NULL,0,pth);
300 strcatW(pth,cszbs);
301 MSI_SetPropertyW(package, ATF, pth);
303 SHGetFolderPathW(NULL,CSIDL_APPDATA,NULL,0,pth);
304 strcatW(pth,cszbs);
305 MSI_SetPropertyW(package, ADF, pth);
307 SHGetFolderPathW(NULL,CSIDL_SYSTEM,NULL,0,pth);
308 strcatW(pth,cszbs);
309 MSI_SetPropertyW(package, SF, pth);
311 SHGetFolderPathW(NULL,CSIDL_LOCAL_APPDATA,NULL,0,pth);
312 strcatW(pth,cszbs);
313 MSI_SetPropertyW(package, LADF, pth);
315 SHGetFolderPathW(NULL,CSIDL_MYPICTURES,NULL,0,pth);
316 strcatW(pth,cszbs);
317 MSI_SetPropertyW(package, MPF, pth);
319 SHGetFolderPathW(NULL,CSIDL_PERSONAL,NULL,0,pth);
320 strcatW(pth,cszbs);
321 MSI_SetPropertyW(package, PF, pth);
323 SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
324 strcatW(pth,cszbs);
325 MSI_SetPropertyW(package, WF, pth);
327 GetTempPathW(MAX_PATH,pth);
328 MSI_SetPropertyW(package, TF, pth);
331 /* in a wine environment the user is always admin and privileged */
332 MSI_SetPropertyW(package,szAdminUser,szOne);
333 MSI_SetPropertyW(package,szPriv,szOne);
335 /* set the os things */
336 OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
337 GetVersionExA(&OSVersion);
338 verval = OSVersion.dwMinorVersion+OSVersion.dwMajorVersion*100;
339 sprintfW(verstr,szFormat,verval);
340 switch (OSVersion.dwPlatformId)
342 case VER_PLATFORM_WIN32_WINDOWS:
343 MSI_SetPropertyW(package,v9x,verstr);
344 break;
345 case VER_PLATFORM_WIN32_NT:
346 MSI_SetPropertyW(package,vNT,verstr);
347 break;
349 sprintfW(verstr,szFormat,OSVersion.dwBuildNumber);
350 MSI_SetPropertyW(package,szWinBuild,verstr);
351 /* just fudge this */
352 MSI_SetPropertyW(package,szSPL,szSix);
354 sprintfW( msiver, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION);
355 MSI_SetPropertyW( package, szVersionMsi, msiver );
357 /* FIXME: these need to be set properly */
359 MSI_SetPropertyW(package,ProgramMenuFolder,PMFPath);
360 MSI_SetPropertyW(package,FavoritesFolder,FFPath);
361 MSI_SetPropertyW(package,FontsFolder,FoFPath);
362 MSI_SetPropertyW(package,SendToFolder,STFPath);
363 MSI_SetPropertyW(package,StartMenuFolder,SMFPath);
364 MSI_SetPropertyW(package,StartupFolder,SFPath);
365 MSI_SetPropertyW(package,TemplateFolder,TFPath);
366 MSI_SetPropertyW(package,DesktopFolder,DFPath);
369 UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
371 UINT rc;
372 MSIDATABASE *db = NULL;
373 MSIPACKAGE *package = NULL;
374 WCHAR uilevel[10];
375 UINT ret = ERROR_FUNCTION_FAILED;
377 static const WCHAR OriginalDatabase[] =
378 {'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
379 static const WCHAR Database[] =
380 {'D','A','T','A','B','A','S','E',0};
381 static const WCHAR szpi[] = {'%','i',0};
382 static const WCHAR szLevel[] = { 'U','I','L','e','v','e','l',0 };
384 TRACE("%s %p\n",debugstr_w(szPackage), pPackage);
386 if (szPackage[0] == '#')
388 INT handle = atoiW(&szPackage[1]);
389 db = msihandle2msiinfo( handle , MSIHANDLETYPE_DATABASE);
391 else
393 rc = MSI_OpenDatabaseW(szPackage, MSIDBOPEN_READONLY, &db);
394 if (rc != ERROR_SUCCESS)
395 return ERROR_FUNCTION_FAILED;
398 package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE),
399 MSI_FreePackage );
401 if (package)
403 msiobj_addref( &db->hdr );
405 package->db = db;
406 package->features = NULL;
407 package->folders = NULL;
408 package->components = NULL;
409 package->files = NULL;
410 package->loaded_features = 0;
411 package->loaded_folders = 0;
412 package->loaded_components= 0;
413 package->loaded_files = 0;
415 /* OK, here is where we do a slew of things to the database to
416 * prep for all that is to come as a package */
418 clone_properties(db);
419 set_installer_properties(package);
420 MSI_SetPropertyW(package, OriginalDatabase, szPackage);
421 MSI_SetPropertyW(package, Database, szPackage);
422 sprintfW(uilevel,szpi,gUILevel);
423 MSI_SetPropertyW(package, szLevel, uilevel);
425 msiobj_addref( &package->hdr );
426 *pPackage = package;
427 ret = ERROR_SUCCESS;
430 if( package )
431 msiobj_release( &package->hdr );
432 if( db )
433 msiobj_release( &db->hdr );
435 return ret;
438 UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
440 MSIPACKAGE *package = NULL;
441 UINT ret;
443 ret = MSI_OpenPackageW( szPackage, &package);
444 if( ret == ERROR_SUCCESS )
446 *phPackage = alloc_msihandle( &package->hdr );
447 msiobj_release( &package->hdr );
449 return ret;
452 UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
454 FIXME("%s 0x%08lx %p\n",debugstr_a(szPackage), dwOptions, phPackage);
455 return ERROR_CALL_NOT_IMPLEMENTED;
458 UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
460 FIXME("%s 0x%08lx %p\n",debugstr_w(szPackage), dwOptions, phPackage);
461 return ERROR_CALL_NOT_IMPLEMENTED;
464 MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
466 MSIPACKAGE *package;
467 MSIHANDLE handle = 0;
469 TRACE("(%ld)\n",hInstall);
471 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
472 if( package)
474 handle = alloc_msihandle( &package->db->hdr );
475 msiobj_release( &package->hdr );
478 return handle;
481 INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType,
482 MSIRECORD *record)
484 DWORD log_type = 0;
485 LPWSTR message;
486 DWORD sz;
487 DWORD total_size = 0;
488 INT msg_field=1;
489 INT i;
490 INT rc;
491 char *msg;
492 int len;
494 TRACE("%x \n",eMessageType);
495 rc = 0;
497 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ERROR)
498 log_type |= INSTALLLOGMODE_ERROR;
499 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_WARNING)
500 log_type |= INSTALLLOGMODE_WARNING;
501 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_USER)
502 log_type |= INSTALLLOGMODE_USER;
503 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INFO)
504 log_type |= INSTALLLOGMODE_INFO;
505 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA)
506 log_type |= INSTALLLOGMODE_COMMONDATA;
507 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART)
508 log_type |= INSTALLLOGMODE_ACTIONSTART;
509 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONDATA)
510 log_type |= INSTALLLOGMODE_ACTIONDATA;
511 /* just a guess */
512 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_PROGRESS)
513 log_type |= 0x800;
515 message = HeapAlloc(GetProcessHeap(),0,1*sizeof (WCHAR));
516 message[0]=0;
517 msg_field = MSI_RecordGetFieldCount(record);
518 for (i = 1; i <= msg_field; i++)
520 LPWSTR tmp;
521 WCHAR number[3];
522 const static WCHAR format[] = { '%','i',':',' ',0};
523 const static WCHAR space[] = { ' ',0};
524 sz = 0;
525 MSI_RecordGetStringW(record,i,NULL,&sz);
526 sz+=4;
527 total_size+=sz*sizeof(WCHAR);
528 tmp = HeapAlloc(GetProcessHeap(),0,sz*sizeof(WCHAR));
529 message = HeapReAlloc(GetProcessHeap(),0,message,total_size*sizeof (WCHAR));
531 MSI_RecordGetStringW(record,i,tmp,&sz);
533 if (msg_field > 1)
535 sprintfW(number,format,i);
536 strcatW(message,number);
538 strcatW(message,tmp);
539 if (msg_field > 1)
540 strcatW(message,space);
542 HeapFree(GetProcessHeap(),0,tmp);
545 TRACE("(%p %lx %lx %s)\n",gUIHandler, gUIFilter, log_type,
546 debugstr_w(message));
548 /* convert it to ASCII */
549 len = WideCharToMultiByte( CP_ACP, 0, message, -1,
550 NULL, 0, NULL, NULL );
551 msg = HeapAlloc( GetProcessHeap(), 0, len );
552 WideCharToMultiByte( CP_ACP, 0, message, -1,
553 msg, len, NULL, NULL );
555 if (gUIHandler && (gUIFilter & log_type))
557 rc = gUIHandler(gUIContext,eMessageType,msg);
560 if ((!rc) && (gszLogFile[0]) && !((eMessageType & 0xff000000) ==
561 INSTALLMESSAGE_PROGRESS))
563 DWORD write;
564 HANDLE log_file = CreateFileW(gszLogFile,GENERIC_WRITE, 0, NULL,
565 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
567 if (log_file != INVALID_HANDLE_VALUE)
569 SetFilePointer(log_file,0, NULL, FILE_END);
570 WriteFile(log_file,msg,strlen(msg),&write,NULL);
571 WriteFile(log_file,"\n",1,&write,NULL);
572 CloseHandle(log_file);
575 HeapFree( GetProcessHeap(), 0, msg );
577 HeapFree(GetProcessHeap(),0,message);
578 return ERROR_SUCCESS;
581 INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
582 MSIHANDLE hRecord)
584 UINT ret = ERROR_INVALID_HANDLE;
585 MSIPACKAGE *package = NULL;
586 MSIRECORD *record = NULL;
588 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
589 if( !package )
590 goto out;
592 record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD );
593 if( !record )
594 goto out;
596 ret = MSI_ProcessMessage( package, eMessageType, record );
598 out:
599 if( package )
600 msiobj_release( &package->hdr );
601 if( record )
602 msiobj_release( &record->hdr );
604 return ret;
607 /* property code */
608 UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue)
610 LPWSTR szwName = NULL, szwValue = NULL;
611 UINT hr = ERROR_INSTALL_FAILURE;
612 UINT len;
614 if (0 == hInstall) {
615 return ERROR_INVALID_HANDLE;
617 if (NULL == szName) {
618 return ERROR_INVALID_PARAMETER;
620 if (NULL == szValue) {
621 return ERROR_INVALID_PARAMETER;
624 len = MultiByteToWideChar( CP_ACP, 0, szName, -1, NULL, 0 );
625 szwName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
626 if( !szwName )
627 goto end;
628 MultiByteToWideChar( CP_ACP, 0, szName, -1, szwName, len );
630 len = MultiByteToWideChar( CP_ACP, 0, szValue, -1, NULL, 0 );
631 szwValue = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
632 if( !szwValue)
633 goto end;
634 MultiByteToWideChar( CP_ACP, 0, szValue , -1, szwValue, len );
636 hr = MsiSetPropertyW( hInstall, szwName, szwValue);
638 end:
639 if( szwName )
640 HeapFree( GetProcessHeap(), 0, szwName );
641 if( szwValue )
642 HeapFree( GetProcessHeap(), 0, szwValue );
644 return hr;
647 UINT MSI_SetPropertyW( MSIPACKAGE *package, LPCWSTR szName, LPCWSTR szValue)
649 MSIQUERY *view;
650 MSIRECORD *row;
651 UINT rc;
652 DWORD sz = 0;
653 static const WCHAR Insert[]=
654 {'I','N','S','E','R','T',' ','i','n','t','o',' ','`','_','P','r','o','p'
655 ,'e','r','t','y','`',' ','(','`','_','P','r','o','p','e','r','t','y','`'
656 ,',','`','V','a','l','u','e','`',')',' ','V','A','L','U','E','S'
657 ,' ','(','?',')',0};
658 static const WCHAR Update[]=
659 {'U','P','D','A','T','E',' ','_','P','r','o','p','e'
660 ,'r','t','y',' ','s','e','t',' ','`','V','a','l','u','e','`',' ','='
661 ,' ','?',' ','w','h','e','r','e',' ','`','_','P','r','o','p'
662 ,'e','r','t','y','`',' ','=',' ','\'','%','s','\'',0};
663 WCHAR Query[1024];
665 TRACE("Setting property (%s %s)\n",debugstr_w(szName),
666 debugstr_w(szValue));
668 rc = MSI_GetPropertyW(package,szName,0,&sz);
669 if (rc==ERROR_MORE_DATA || rc == ERROR_SUCCESS)
671 sprintfW(Query,Update,szName);
673 row = MSI_CreateRecord(1);
674 MSI_RecordSetStringW(row,1,szValue);
677 else
679 strcpyW(Query,Insert);
681 row = MSI_CreateRecord(2);
682 MSI_RecordSetStringW(row,1,szName);
683 MSI_RecordSetStringW(row,2,szValue);
687 rc = MSI_DatabaseOpenViewW(package->db,Query,&view);
688 if (rc!= ERROR_SUCCESS)
690 msiobj_release(&row->hdr);
691 return rc;
694 rc = MSI_ViewExecute(view,row);
696 msiobj_release(&row->hdr);
697 MSI_ViewClose(view);
698 msiobj_release(&view->hdr);
700 return rc;
703 UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue)
705 MSIPACKAGE *package;
706 UINT ret;
708 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
709 if( !package)
710 return ERROR_INVALID_HANDLE;
711 ret = MSI_SetPropertyW( package, szName, szValue);
712 msiobj_release( &package->hdr );
713 return ret;
716 UINT WINAPI MsiGetPropertyA(MSIHANDLE hInstall, LPCSTR szName, LPSTR szValueBuf, DWORD* pchValueBuf)
718 LPWSTR szwName = NULL, szwValueBuf = NULL;
719 UINT hr = ERROR_INSTALL_FAILURE;
721 if (0 == hInstall) {
722 return ERROR_INVALID_HANDLE;
724 if (NULL == szName) {
725 return ERROR_INVALID_PARAMETER;
728 TRACE("%lu %s %lu\n", hInstall, debugstr_a(szName), *pchValueBuf);
730 if (NULL != szValueBuf && NULL == pchValueBuf) {
731 return ERROR_INVALID_PARAMETER;
733 if( szName )
735 UINT len = MultiByteToWideChar( CP_ACP, 0, szName, -1, NULL, 0 );
736 szwName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
737 if( !szwName )
738 goto end;
739 MultiByteToWideChar( CP_ACP, 0, szName, -1, szwName, len );
740 } else {
741 return ERROR_INVALID_PARAMETER;
743 if( szValueBuf )
745 szwValueBuf = HeapAlloc( GetProcessHeap(), 0, (*pchValueBuf) * sizeof(WCHAR) );
746 if( !szwValueBuf )
747 goto end;
750 if( *pchValueBuf > 0 )
752 /* be sure to blank the string first */
753 szValueBuf[0]=0;
756 hr = MsiGetPropertyW( hInstall, szwName, szwValueBuf, pchValueBuf );
758 if( *pchValueBuf > 0 )
760 WideCharToMultiByte(CP_ACP, 0, szwValueBuf, -1, szValueBuf, *pchValueBuf, NULL, NULL);
763 end:
764 if( szwName )
765 HeapFree( GetProcessHeap(), 0, szwName );
766 if( szwValueBuf )
767 HeapFree( GetProcessHeap(), 0, szwValueBuf );
769 return hr;
772 UINT MSI_GetPropertyW(MSIPACKAGE *package, LPCWSTR szName,
773 LPWSTR szValueBuf, DWORD* pchValueBuf)
775 MSIQUERY *view;
776 MSIRECORD *row;
777 UINT rc;
778 WCHAR Query[1024]=
779 {'s','e','l','e','c','t',' ','V','a','l','u','e',' ','f','r','o','m',' '
780 ,'_','P','r','o','p','e','r','t','y',' ','w','h','e','r','e',' '
781 ,'_','P','r','o','p','e','r','t','y','=','`',0};
783 static const WCHAR szEnd[]={'`',0};
785 if (NULL == szName) {
786 return ERROR_INVALID_PARAMETER;
789 strcatW(Query,szName);
790 strcatW(Query,szEnd);
792 rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
793 if (rc == ERROR_SUCCESS)
795 DWORD sz;
796 WCHAR value[0x100];
798 /* even on unsuccessful lookup native msi blanks this string */
799 if (*pchValueBuf > 0)
800 szValueBuf[0] = 0;
802 rc = MSI_ViewExecute(view, 0);
803 if (rc != ERROR_SUCCESS)
805 MSI_ViewClose(view);
806 msiobj_release(&view->hdr);
807 return rc;
810 rc = MSI_ViewFetch(view,&row);
811 if (rc == ERROR_SUCCESS)
813 sz=0x100;
814 rc = MSI_RecordGetStringW(row,1,value,&sz);
815 strncpyW(szValueBuf,value,min(sz+1,*pchValueBuf));
816 *pchValueBuf = sz+1;
817 msiobj_release(&row->hdr);
819 MSI_ViewClose(view);
820 msiobj_release(&view->hdr);
823 if (rc == ERROR_SUCCESS)
824 TRACE("returning %s for property %s\n", debugstr_w(szValueBuf),
825 debugstr_w(szName));
826 else
828 *pchValueBuf = 0;
829 TRACE("property not found\n");
832 return rc;
836 UINT WINAPI MsiGetPropertyW(MSIHANDLE hInstall, LPCWSTR szName,
837 LPWSTR szValueBuf, DWORD* pchValueBuf)
839 MSIPACKAGE *package;
840 UINT ret;
842 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
843 if( !package)
844 return ERROR_INVALID_HANDLE;
845 ret = MSI_GetPropertyW(package, szName, szValueBuf, pchValueBuf );
846 msiobj_release( &package->hdr );
847 return ret;