- action.c is getting too big, so split out all the handling of
[wine.git] / dlls / msi / package.c
blob54598aa7b639c86994559841bd8732173db6150b
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_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 HeapFree( GetProcessHeap(), 0, szwPack );
80 return ret;
84 static const UINT clone_properties(MSIDATABASE *db)
86 MSIQUERY * view = NULL;
87 UINT rc;
88 static const WCHAR CreateSql[] = {
89 'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','_','P','r','o',
90 'p','e','r','t','y','`',' ','(',' ','`','_','P','r','o','p','e','r','t',
91 'y','`',' ','C','H','A','R','(','5','6',')',' ','N','O','T',' ','N','U',
92 'L','L',',',' ','`','V','a','l','u','e','`',' ','C','H','A','R','(','9',
93 '8',')',' ','N','O','T',' ','N','U','L','L',' ','P','R','I','M','A','R',
94 'Y',' ','K','E','Y',' ','`','_','P','r','o','p','e','r','t','y','`',')',0};
95 static const WCHAR Query[] = {
96 'S','E','L','E','C','T',' ','*',' ',
97 'f','r','o','m',' ','P','r','o','p','e','r','t','y',0};
98 static const WCHAR Insert[] = {
99 'I','N','S','E','R','T',' ','i','n','t','o',' ',
100 '`','_','P','r','o','p','e','r','t','y','`',' ',
101 '(','`','_','P','r','o','p','e','r','t','y','`',',',
102 '`','V','a','l','u','e','`',')',' ',
103 'V','A','L','U','E','S',' ','(','?',',','?',')',0};
105 /* create the temporary properties table */
106 rc = MSI_DatabaseOpenViewW(db, CreateSql, &view);
107 if (rc != ERROR_SUCCESS)
108 return rc;
109 rc = MSI_ViewExecute(view,0);
110 MSI_ViewClose(view);
111 msiobj_release(&view->hdr);
112 if (rc != ERROR_SUCCESS)
113 return rc;
115 /* clone the existing properties */
116 rc = MSI_DatabaseOpenViewW(db, Query, &view);
117 if (rc != ERROR_SUCCESS)
118 return rc;
120 rc = MSI_ViewExecute(view, 0);
121 if (rc != ERROR_SUCCESS)
123 MSI_ViewClose(view);
124 msiobj_release(&view->hdr);
125 return rc;
127 while (1)
129 MSIRECORD * row;
130 MSIQUERY * view2;
132 rc = MSI_ViewFetch(view,&row);
133 if (rc != ERROR_SUCCESS)
134 break;
136 rc = MSI_DatabaseOpenViewW(db,Insert,&view2);
137 if (rc!= ERROR_SUCCESS)
138 continue;
139 rc = MSI_ViewExecute(view2,row);
140 MSI_ViewClose(view2);
141 msiobj_release(&view2->hdr);
143 if (rc == ERROR_SUCCESS)
144 msiobj_release(&row->hdr);
146 MSI_ViewClose(view);
147 msiobj_release(&view->hdr);
149 return rc;
153 * There are a whole slew of these we need to set
156 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/properties.asp
158 static VOID set_installer_properties(MSIPACKAGE *package)
160 WCHAR pth[MAX_PATH];
161 WCHAR *ptr;
162 OSVERSIONINFOA OSVersion;
163 DWORD verval;
164 WCHAR verstr[10], bufstr[20];
165 HDC dc;
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( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION);
365 MSI_SetPropertyW( package, szVersionMsi, bufstr );
367 /* Screen properties. */
368 dc = GetDC(0);
369 sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, HORZRES ) );
370 MSI_SetPropertyW( package, szScreenX, bufstr );
371 sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, VERTRES ));
372 MSI_SetPropertyW( package, szScreenY, bufstr );
373 sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, BITSPIXEL ));
374 MSI_SetPropertyW( package, szColorBits, bufstr );
375 ReleaseDC(0, dc);
378 UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
380 UINT rc;
381 MSIDATABASE *db = NULL;
382 MSIPACKAGE *package = NULL;
383 WCHAR uilevel[10];
384 UINT ret = ERROR_FUNCTION_FAILED;
386 static const WCHAR OriginalDatabase[] =
387 {'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
388 static const WCHAR Database[] =
389 {'D','A','T','A','B','A','S','E',0};
390 static const WCHAR szpi[] = {'%','i',0};
391 static const WCHAR szLevel[] = { 'U','I','L','e','v','e','l',0 };
393 TRACE("%s %p\n",debugstr_w(szPackage), pPackage);
395 if (szPackage[0] == '#')
397 INT handle = atoiW(&szPackage[1]);
398 db = msihandle2msiinfo( handle , MSIHANDLETYPE_DATABASE);
400 else
402 rc = MSI_OpenDatabaseW(szPackage, MSIDBOPEN_READONLY, &db);
403 if (rc != ERROR_SUCCESS)
404 return ERROR_FUNCTION_FAILED;
407 package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE),
408 MSI_FreePackage );
410 if (package)
412 msiobj_addref( &db->hdr );
414 package->db = db;
415 package->features = NULL;
416 package->folders = NULL;
417 package->components = NULL;
418 package->files = NULL;
419 package->loaded_features = 0;
420 package->loaded_folders = 0;
421 package->loaded_components= 0;
422 package->loaded_files = 0;
423 package->ActionFormat = NULL;
424 package->LastAction = NULL;
426 /* OK, here is where we do a slew of things to the database to
427 * prep for all that is to come as a package */
429 clone_properties(db);
430 set_installer_properties(package);
431 MSI_SetPropertyW(package, OriginalDatabase, szPackage);
432 MSI_SetPropertyW(package, Database, szPackage);
433 sprintfW(uilevel,szpi,gUILevel);
434 MSI_SetPropertyW(package, szLevel, uilevel);
436 msiobj_addref( &package->hdr );
437 *pPackage = package;
438 ret = ERROR_SUCCESS;
441 if( package )
442 msiobj_release( &package->hdr );
443 if( db )
444 msiobj_release( &db->hdr );
446 return ret;
449 UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
451 MSIPACKAGE *package = NULL;
452 UINT ret;
454 ret = MSI_OpenPackageW( szPackage, &package);
455 if( ret == ERROR_SUCCESS )
457 *phPackage = alloc_msihandle( &package->hdr );
458 msiobj_release( &package->hdr );
460 return ret;
463 UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
465 FIXME("%s 0x%08lx %p\n",debugstr_a(szPackage), dwOptions, phPackage);
466 return ERROR_CALL_NOT_IMPLEMENTED;
469 UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
471 FIXME("%s 0x%08lx %p\n",debugstr_w(szPackage), dwOptions, phPackage);
472 return ERROR_CALL_NOT_IMPLEMENTED;
475 MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
477 MSIPACKAGE *package;
478 MSIHANDLE handle = 0;
480 TRACE("(%ld)\n",hInstall);
482 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
483 if( package)
485 handle = alloc_msihandle( &package->db->hdr );
486 msiobj_release( &package->hdr );
489 return handle;
492 INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType,
493 MSIRECORD *record)
495 DWORD log_type = 0;
496 LPWSTR message;
497 DWORD sz;
498 DWORD total_size = 0;
499 INT msg_field=1;
500 INT i;
501 INT rc;
502 char *msg;
503 int len;
505 TRACE("%x \n",eMessageType);
506 rc = 0;
508 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ERROR)
509 log_type |= INSTALLLOGMODE_ERROR;
510 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_WARNING)
511 log_type |= INSTALLLOGMODE_WARNING;
512 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_USER)
513 log_type |= INSTALLLOGMODE_USER;
514 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INFO)
515 log_type |= INSTALLLOGMODE_INFO;
516 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA)
517 log_type |= INSTALLLOGMODE_COMMONDATA;
518 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART)
519 log_type |= INSTALLLOGMODE_ACTIONSTART;
520 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONDATA)
521 log_type |= INSTALLLOGMODE_ACTIONDATA;
522 /* just a guess */
523 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_PROGRESS)
524 log_type |= 0x800;
526 message = HeapAlloc(GetProcessHeap(),0,1*sizeof (WCHAR));
527 message[0]=0;
528 msg_field = MSI_RecordGetFieldCount(record);
529 for (i = 1; i <= msg_field; i++)
531 LPWSTR tmp;
532 WCHAR number[3];
533 const static WCHAR format[] = { '%','i',':',' ',0};
534 const static WCHAR space[] = { ' ',0};
535 sz = 0;
536 MSI_RecordGetStringW(record,i,NULL,&sz);
537 sz+=4;
538 total_size+=sz*sizeof(WCHAR);
539 tmp = HeapAlloc(GetProcessHeap(),0,sz*sizeof(WCHAR));
540 message = HeapReAlloc(GetProcessHeap(),0,message,total_size*sizeof (WCHAR));
542 MSI_RecordGetStringW(record,i,tmp,&sz);
544 if (msg_field > 1)
546 sprintfW(number,format,i);
547 strcatW(message,number);
549 strcatW(message,tmp);
550 if (msg_field > 1)
551 strcatW(message,space);
553 HeapFree(GetProcessHeap(),0,tmp);
556 TRACE("(%p %lx %lx %s)\n",gUIHandlerA, gUIFilter, log_type,
557 debugstr_w(message));
559 /* convert it to ASCII */
560 len = WideCharToMultiByte( CP_ACP, 0, message, -1,
561 NULL, 0, NULL, NULL );
562 msg = HeapAlloc( GetProcessHeap(), 0, len );
563 WideCharToMultiByte( CP_ACP, 0, message, -1,
564 msg, len, NULL, NULL );
566 if (gUIHandlerA && (gUIFilter & log_type))
568 rc = gUIHandlerA(gUIContext,eMessageType,msg);
571 if ((!rc) && (gszLogFile[0]) && !((eMessageType & 0xff000000) ==
572 INSTALLMESSAGE_PROGRESS))
574 DWORD write;
575 HANDLE log_file = CreateFileW(gszLogFile,GENERIC_WRITE, 0, NULL,
576 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
578 if (log_file != INVALID_HANDLE_VALUE)
580 SetFilePointer(log_file,0, NULL, FILE_END);
581 WriteFile(log_file,msg,strlen(msg),&write,NULL);
582 WriteFile(log_file,"\n",1,&write,NULL);
583 CloseHandle(log_file);
586 HeapFree( GetProcessHeap(), 0, msg );
588 HeapFree(GetProcessHeap(),0,message);
589 return ERROR_SUCCESS;
592 INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
593 MSIHANDLE hRecord)
595 UINT ret = ERROR_INVALID_HANDLE;
596 MSIPACKAGE *package = NULL;
597 MSIRECORD *record = NULL;
599 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
600 if( !package )
601 goto out;
603 record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD );
604 if( !record )
605 goto out;
607 ret = MSI_ProcessMessage( package, eMessageType, record );
609 out:
610 if( package )
611 msiobj_release( &package->hdr );
612 if( record )
613 msiobj_release( &record->hdr );
615 return ret;
618 /* property code */
619 UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue)
621 LPWSTR szwName = NULL, szwValue = NULL;
622 UINT hr = ERROR_INSTALL_FAILURE;
623 UINT len;
625 if (0 == hInstall) {
626 return ERROR_INVALID_HANDLE;
628 if (NULL == szName) {
629 return ERROR_INVALID_PARAMETER;
631 if (NULL == szValue) {
632 return ERROR_INVALID_PARAMETER;
635 len = MultiByteToWideChar( CP_ACP, 0, szName, -1, NULL, 0 );
636 szwName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
637 if( !szwName )
638 goto end;
639 MultiByteToWideChar( CP_ACP, 0, szName, -1, szwName, len );
641 len = MultiByteToWideChar( CP_ACP, 0, szValue, -1, NULL, 0 );
642 szwValue = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
643 if( !szwValue)
644 goto end;
645 MultiByteToWideChar( CP_ACP, 0, szValue , -1, szwValue, len );
647 hr = MsiSetPropertyW( hInstall, szwName, szwValue);
649 end:
650 HeapFree( GetProcessHeap(), 0, szwName );
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;