Get real screen properties.
[wine/testsucceed.git] / dlls / msi / package.c
blob837629d8c68413abf9832f5309070fa09c820576
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 if( szwPack )
80 HeapFree( GetProcessHeap(), 0, szwPack );
82 return ret;
86 static const UINT clone_properties(MSIDATABASE *db)
88 MSIQUERY * view = NULL;
89 UINT rc;
90 static const WCHAR CreateSql[] = {
91 'C','R','E','A','T','E',' ','T','A','B','L','E',' ','`','_','P','r','o',
92 'p','e','r','t','y','`',' ','(',' ','`','_','P','r','o','p','e','r','t',
93 'y','`',' ','C','H','A','R','(','5','6',')',' ','N','O','T',' ','N','U',
94 'L','L',',',' ','`','V','a','l','u','e','`',' ','C','H','A','R','(','9',
95 '8',')',' ','N','O','T',' ','N','U','L','L',' ','P','R','I','M','A','R',
96 'Y',' ','K','E','Y',' ','`','_','P','r','o','p','e','r','t','y','`',')',0};
97 static const WCHAR Query[] = {
98 'S','E','L','E','C','T',' ','*',' ',
99 'f','r','o','m',' ','P','r','o','p','e','r','t','y',0};
100 static const WCHAR Insert[] = {
101 'I','N','S','E','R','T',' ','i','n','t','o',' ',
102 '`','_','P','r','o','p','e','r','t','y','`',' ',
103 '(','`','_','P','r','o','p','e','r','t','y','`',',',
104 '`','V','a','l','u','e','`',')',' ',
105 'V','A','L','U','E','S',' ','(','?',')',0};
107 /* create the temporary properties table */
108 rc = MSI_DatabaseOpenViewW(db, CreateSql, &view);
109 if (rc != ERROR_SUCCESS)
110 return rc;
111 rc = MSI_ViewExecute(view,0);
112 MSI_ViewClose(view);
113 msiobj_release(&view->hdr);
114 if (rc != ERROR_SUCCESS)
115 return rc;
117 /* clone the existing properties */
118 rc = MSI_DatabaseOpenViewW(db, Query, &view);
119 if (rc != ERROR_SUCCESS)
120 return rc;
122 rc = MSI_ViewExecute(view, 0);
123 if (rc != ERROR_SUCCESS)
125 MSI_ViewClose(view);
126 msiobj_release(&view->hdr);
127 return rc;
129 while (1)
131 MSIRECORD * row;
132 MSIQUERY * view2;
134 rc = MSI_ViewFetch(view,&row);
135 if (rc != ERROR_SUCCESS)
136 break;
138 rc = MSI_DatabaseOpenViewW(db,Insert,&view2);
139 if (rc!= ERROR_SUCCESS)
140 continue;
141 rc = MSI_ViewExecute(view2,row);
142 MSI_ViewClose(view2);
143 msiobj_release(&view2->hdr);
145 if (rc == ERROR_SUCCESS)
146 msiobj_release(&row->hdr);
148 MSI_ViewClose(view);
149 msiobj_release(&view->hdr);
151 return rc;
155 * There are a whole slew of these we need to set
158 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/properties.asp
160 static VOID set_installer_properties(MSIPACKAGE *package)
162 WCHAR pth[MAX_PATH];
163 WCHAR *ptr;
164 OSVERSIONINFOA OSVersion;
165 DWORD verval;
166 WCHAR verstr[10], bufstr[20];
167 HDC dc;
169 static const WCHAR cszbs[]={'\\',0};
170 static const WCHAR CFF[] =
171 {'C','o','m','m','o','n','F','i','l','e','s','F','o','l','d','e','r',0};
172 static const WCHAR PFF[] =
173 {'P','r','o','g','r','a','m','F','i','l','e','s','F','o','l','d','e','r',0};
174 static const WCHAR CADF[] =
175 {'C','o','m','m','o','n','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
176 static const WCHAR FaF[] =
177 {'F','a','v','o','r','i','t','e','s','F','o','l','d','e','r',0};
178 static const WCHAR FoF[] =
179 {'F','o','n','t','s','F','o','l','d','e','r',0};
180 static const WCHAR SendTF[] =
181 {'S','e','n','d','T','o','F','o','l','d','e','r',0};
182 static const WCHAR SMF[] =
183 {'S','t','a','r','t','M','e','n','u','F','o','l','d','e','r',0};
184 static const WCHAR StF[] =
185 {'S','t','a','r','t','u','p','F','o','l','d','e','r',0};
186 static const WCHAR TemplF[] =
187 {'T','e','m','p','l','a','t','e','F','o','l','d','e','r',0};
188 static const WCHAR DF[] =
189 {'D','e','s','k','t','o','p','F','o','l','d','e','r',0};
190 static const WCHAR PMF[] =
191 {'P','r','o','g','r','a','m','M','e','n','u','F','o','l','d','e','r',0};
192 static const WCHAR ATF[] =
193 {'A','d','m','i','n','T','o','o','l','s','F','o','l','d','e','r',0};
194 static const WCHAR ADF[] =
195 {'A','p','p','D','a','t','a','F','o','l','d','e','r',0};
196 static const WCHAR SF[] =
197 {'S','y','s','t','e','m','F','o','l','d','e','r',0};
198 static const WCHAR SF16[] =
199 {'S','y','s','t','e','m','1','6','F','o','l','d','e','r',0};
200 static const WCHAR LADF[] =
201 {'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
202 static const WCHAR MPF[] =
203 {'M','y','P','i','c','t','u','r','e','s','F','o','l','d','e','r',0};
204 static const WCHAR PF[] =
205 {'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0};
206 static const WCHAR WF[] =
207 {'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
208 static const WCHAR WV[] =
209 {'W','i','n','d','o','w','s','V','o','l','u','m','e',0};
210 static const WCHAR TF[]=
211 {'T','e','m','p','F','o','l','d','e','r',0};
212 static const WCHAR szAdminUser[] =
213 {'A','d','m','i','n','U','s','e','r',0};
214 static const WCHAR szPriv[] =
215 {'P','r','i','v','i','l','e','g','e','d',0};
216 static const WCHAR szOne[] =
217 {'1',0};
218 static const WCHAR v9x[] = { 'V','e','r','s','i','o','n','9','X',0 };
219 static const WCHAR vNT[] = { 'V','e','r','s','i','o','n','N','T',0 };
220 static const WCHAR szFormat[] = {'%','l','i',0};
221 static const WCHAR szWinBuild[] =
222 {'W','i','n','d','o','w','s','B','u','i','l','d', 0 };
223 static const WCHAR szSPL[] =
224 {'S','e','r','v','i','c','e','P','a','c','k','L','e','v','e','l',0 };
225 static const WCHAR szSix[] = {'6',0 };
227 static const WCHAR szVersionMsi[] = { 'V','e','r','s','i','o','n','M','s','i',0 };
228 static const WCHAR szFormat2[] = {'%','l','i','.','%','l','i',0};
229 /* Screen properties */
230 static const WCHAR szScreenX[] = {'S','c','r','e','e','n','X',0};
231 static const WCHAR szScreenY[] = {'S','c','r','e','e','n','Y',0};
232 static const WCHAR szColorBits[] = {'C','o','l','o','r','B','i','t','s',0};
233 static const WCHAR szScreenFormat[] = {'%','d',0};
236 * Other things I notice set
238 SystemLanguageID
239 ComputerName
240 UserLanguageID
241 LogonUser
242 VirtualMemory
243 PhysicalMemory
244 Intel
245 ShellAdvSupport
246 DefaultUIFont
247 VersionDatabase
248 PackagecodeChanging
249 ProductState
250 CaptionHeight
251 BorderTop
252 BorderSide
253 TextHeight
254 RedirectedDllSupport
255 Time
256 Date
257 Privileged
260 SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES_COMMON,NULL,0,pth);
261 strcatW(pth,cszbs);
262 MSI_SetPropertyW(package, CFF, pth);
264 SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES,NULL,0,pth);
265 strcatW(pth,cszbs);
266 MSI_SetPropertyW(package, PFF, pth);
268 SHGetFolderPathW(NULL,CSIDL_COMMON_APPDATA,NULL,0,pth);
269 strcatW(pth,cszbs);
270 MSI_SetPropertyW(package, CADF, pth);
272 SHGetFolderPathW(NULL,CSIDL_FAVORITES,NULL,0,pth);
273 strcatW(pth,cszbs);
274 MSI_SetPropertyW(package, FaF, pth);
276 SHGetFolderPathW(NULL,CSIDL_FONTS,NULL,0,pth);
277 strcatW(pth,cszbs);
278 MSI_SetPropertyW(package, FoF, pth);
280 SHGetFolderPathW(NULL,CSIDL_SENDTO,NULL,0,pth);
281 strcatW(pth,cszbs);
282 MSI_SetPropertyW(package, SendTF, pth);
284 SHGetFolderPathW(NULL,CSIDL_STARTMENU,NULL,0,pth);
285 strcatW(pth,cszbs);
286 MSI_SetPropertyW(package, SMF, pth);
288 SHGetFolderPathW(NULL,CSIDL_STARTUP,NULL,0,pth);
289 strcatW(pth,cszbs);
290 MSI_SetPropertyW(package, StF, pth);
292 SHGetFolderPathW(NULL,CSIDL_TEMPLATES,NULL,0,pth);
293 strcatW(pth,cszbs);
294 MSI_SetPropertyW(package, TemplF, pth);
296 SHGetFolderPathW(NULL,CSIDL_DESKTOP,NULL,0,pth);
297 strcatW(pth,cszbs);
298 MSI_SetPropertyW(package, DF, pth);
300 SHGetFolderPathW(NULL,CSIDL_PROGRAMS,NULL,0,pth);
301 strcatW(pth,cszbs);
302 MSI_SetPropertyW(package, PMF, pth);
304 SHGetFolderPathW(NULL,CSIDL_ADMINTOOLS,NULL,0,pth);
305 strcatW(pth,cszbs);
306 MSI_SetPropertyW(package, ATF, pth);
308 SHGetFolderPathW(NULL,CSIDL_APPDATA,NULL,0,pth);
309 strcatW(pth,cszbs);
310 MSI_SetPropertyW(package, ADF, pth);
312 SHGetFolderPathW(NULL,CSIDL_SYSTEM,NULL,0,pth);
313 strcatW(pth,cszbs);
314 MSI_SetPropertyW(package, SF, pth);
315 MSI_SetPropertyW(package, SF16, pth);
317 SHGetFolderPathW(NULL,CSIDL_LOCAL_APPDATA,NULL,0,pth);
318 strcatW(pth,cszbs);
319 MSI_SetPropertyW(package, LADF, pth);
321 SHGetFolderPathW(NULL,CSIDL_MYPICTURES,NULL,0,pth);
322 strcatW(pth,cszbs);
323 MSI_SetPropertyW(package, MPF, pth);
325 SHGetFolderPathW(NULL,CSIDL_PERSONAL,NULL,0,pth);
326 strcatW(pth,cszbs);
327 MSI_SetPropertyW(package, PF, pth);
329 SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
330 strcatW(pth,cszbs);
331 MSI_SetPropertyW(package, WF, pth);
333 SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
334 ptr = strchrW(pth,'\\');
335 if (ptr)
336 *(ptr+1) = 0;
337 MSI_SetPropertyW(package, WV, pth);
339 GetTempPathW(MAX_PATH,pth);
340 MSI_SetPropertyW(package, TF, pth);
343 /* in a wine environment the user is always admin and privileged */
344 MSI_SetPropertyW(package,szAdminUser,szOne);
345 MSI_SetPropertyW(package,szPriv,szOne);
347 /* set the os things */
348 OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
349 GetVersionExA(&OSVersion);
350 verval = OSVersion.dwMinorVersion+OSVersion.dwMajorVersion*100;
351 sprintfW(verstr,szFormat,verval);
352 switch (OSVersion.dwPlatformId)
354 case VER_PLATFORM_WIN32_WINDOWS:
355 MSI_SetPropertyW(package,v9x,verstr);
356 break;
357 case VER_PLATFORM_WIN32_NT:
358 MSI_SetPropertyW(package,vNT,verstr);
359 break;
361 sprintfW(verstr,szFormat,OSVersion.dwBuildNumber);
362 MSI_SetPropertyW(package,szWinBuild,verstr);
363 /* just fudge this */
364 MSI_SetPropertyW(package,szSPL,szSix);
366 sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION);
367 MSI_SetPropertyW( package, szVersionMsi, bufstr );
369 /* Screen properties. */
370 dc = GetDC(0);
371 sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, HORZRES ) );
372 MSI_SetPropertyW( package, szScreenX, bufstr );
373 sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, VERTRES ));
374 MSI_SetPropertyW( package, szScreenY, bufstr );
375 sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, BITSPIXEL ));
376 MSI_SetPropertyW( package, szColorBits, bufstr );
377 ReleaseDC(0, dc);
380 UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
382 UINT rc;
383 MSIDATABASE *db = NULL;
384 MSIPACKAGE *package = NULL;
385 WCHAR uilevel[10];
386 UINT ret = ERROR_FUNCTION_FAILED;
388 static const WCHAR OriginalDatabase[] =
389 {'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
390 static const WCHAR Database[] =
391 {'D','A','T','A','B','A','S','E',0};
392 static const WCHAR szpi[] = {'%','i',0};
393 static const WCHAR szLevel[] = { 'U','I','L','e','v','e','l',0 };
395 TRACE("%s %p\n",debugstr_w(szPackage), pPackage);
397 if (szPackage[0] == '#')
399 INT handle = atoiW(&szPackage[1]);
400 db = msihandle2msiinfo( handle , MSIHANDLETYPE_DATABASE);
402 else
404 rc = MSI_OpenDatabaseW(szPackage, MSIDBOPEN_READONLY, &db);
405 if (rc != ERROR_SUCCESS)
406 return ERROR_FUNCTION_FAILED;
409 package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE),
410 MSI_FreePackage );
412 if (package)
414 msiobj_addref( &db->hdr );
416 package->db = db;
417 package->features = NULL;
418 package->folders = NULL;
419 package->components = NULL;
420 package->files = NULL;
421 package->loaded_features = 0;
422 package->loaded_folders = 0;
423 package->loaded_components= 0;
424 package->loaded_files = 0;
425 package->ActionFormat = NULL;
426 package->LastAction = NULL;
428 /* OK, here is where we do a slew of things to the database to
429 * prep for all that is to come as a package */
431 clone_properties(db);
432 set_installer_properties(package);
433 MSI_SetPropertyW(package, OriginalDatabase, szPackage);
434 MSI_SetPropertyW(package, Database, szPackage);
435 sprintfW(uilevel,szpi,gUILevel);
436 MSI_SetPropertyW(package, szLevel, uilevel);
438 msiobj_addref( &package->hdr );
439 *pPackage = package;
440 ret = ERROR_SUCCESS;
443 if( package )
444 msiobj_release( &package->hdr );
445 if( db )
446 msiobj_release( &db->hdr );
448 return ret;
451 UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
453 MSIPACKAGE *package = NULL;
454 UINT ret;
456 ret = MSI_OpenPackageW( szPackage, &package);
457 if( ret == ERROR_SUCCESS )
459 *phPackage = alloc_msihandle( &package->hdr );
460 msiobj_release( &package->hdr );
462 return ret;
465 UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
467 FIXME("%s 0x%08lx %p\n",debugstr_a(szPackage), dwOptions, phPackage);
468 return ERROR_CALL_NOT_IMPLEMENTED;
471 UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
473 FIXME("%s 0x%08lx %p\n",debugstr_w(szPackage), dwOptions, phPackage);
474 return ERROR_CALL_NOT_IMPLEMENTED;
477 MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
479 MSIPACKAGE *package;
480 MSIHANDLE handle = 0;
482 TRACE("(%ld)\n",hInstall);
484 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
485 if( package)
487 handle = alloc_msihandle( &package->db->hdr );
488 msiobj_release( &package->hdr );
491 return handle;
494 INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType,
495 MSIRECORD *record)
497 DWORD log_type = 0;
498 LPWSTR message;
499 DWORD sz;
500 DWORD total_size = 0;
501 INT msg_field=1;
502 INT i;
503 INT rc;
504 char *msg;
505 int len;
507 TRACE("%x \n",eMessageType);
508 rc = 0;
510 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ERROR)
511 log_type |= INSTALLLOGMODE_ERROR;
512 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_WARNING)
513 log_type |= INSTALLLOGMODE_WARNING;
514 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_USER)
515 log_type |= INSTALLLOGMODE_USER;
516 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INFO)
517 log_type |= INSTALLLOGMODE_INFO;
518 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA)
519 log_type |= INSTALLLOGMODE_COMMONDATA;
520 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART)
521 log_type |= INSTALLLOGMODE_ACTIONSTART;
522 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONDATA)
523 log_type |= INSTALLLOGMODE_ACTIONDATA;
524 /* just a guess */
525 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_PROGRESS)
526 log_type |= 0x800;
528 message = HeapAlloc(GetProcessHeap(),0,1*sizeof (WCHAR));
529 message[0]=0;
530 msg_field = MSI_RecordGetFieldCount(record);
531 for (i = 1; i <= msg_field; i++)
533 LPWSTR tmp;
534 WCHAR number[3];
535 const static WCHAR format[] = { '%','i',':',' ',0};
536 const static WCHAR space[] = { ' ',0};
537 sz = 0;
538 MSI_RecordGetStringW(record,i,NULL,&sz);
539 sz+=4;
540 total_size+=sz*sizeof(WCHAR);
541 tmp = HeapAlloc(GetProcessHeap(),0,sz*sizeof(WCHAR));
542 message = HeapReAlloc(GetProcessHeap(),0,message,total_size*sizeof (WCHAR));
544 MSI_RecordGetStringW(record,i,tmp,&sz);
546 if (msg_field > 1)
548 sprintfW(number,format,i);
549 strcatW(message,number);
551 strcatW(message,tmp);
552 if (msg_field > 1)
553 strcatW(message,space);
555 HeapFree(GetProcessHeap(),0,tmp);
558 TRACE("(%p %lx %lx %s)\n",gUIHandler, gUIFilter, log_type,
559 debugstr_w(message));
561 /* convert it to ASCII */
562 len = WideCharToMultiByte( CP_ACP, 0, message, -1,
563 NULL, 0, NULL, NULL );
564 msg = HeapAlloc( GetProcessHeap(), 0, len );
565 WideCharToMultiByte( CP_ACP, 0, message, -1,
566 msg, len, NULL, NULL );
568 if (gUIHandler && (gUIFilter & log_type))
570 rc = gUIHandler(gUIContext,eMessageType,msg);
573 if ((!rc) && (gszLogFile[0]) && !((eMessageType & 0xff000000) ==
574 INSTALLMESSAGE_PROGRESS))
576 DWORD write;
577 HANDLE log_file = CreateFileW(gszLogFile,GENERIC_WRITE, 0, NULL,
578 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
580 if (log_file != INVALID_HANDLE_VALUE)
582 SetFilePointer(log_file,0, NULL, FILE_END);
583 WriteFile(log_file,msg,strlen(msg),&write,NULL);
584 WriteFile(log_file,"\n",1,&write,NULL);
585 CloseHandle(log_file);
588 HeapFree( GetProcessHeap(), 0, msg );
590 HeapFree(GetProcessHeap(),0,message);
591 return ERROR_SUCCESS;
594 INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
595 MSIHANDLE hRecord)
597 UINT ret = ERROR_INVALID_HANDLE;
598 MSIPACKAGE *package = NULL;
599 MSIRECORD *record = NULL;
601 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
602 if( !package )
603 goto out;
605 record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD );
606 if( !record )
607 goto out;
609 ret = MSI_ProcessMessage( package, eMessageType, record );
611 out:
612 if( package )
613 msiobj_release( &package->hdr );
614 if( record )
615 msiobj_release( &record->hdr );
617 return ret;
620 /* property code */
621 UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue)
623 LPWSTR szwName = NULL, szwValue = NULL;
624 UINT hr = ERROR_INSTALL_FAILURE;
625 UINT len;
627 if (0 == hInstall) {
628 return ERROR_INVALID_HANDLE;
630 if (NULL == szName) {
631 return ERROR_INVALID_PARAMETER;
633 if (NULL == szValue) {
634 return ERROR_INVALID_PARAMETER;
637 len = MultiByteToWideChar( CP_ACP, 0, szName, -1, NULL, 0 );
638 szwName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
639 if( !szwName )
640 goto end;
641 MultiByteToWideChar( CP_ACP, 0, szName, -1, szwName, len );
643 len = MultiByteToWideChar( CP_ACP, 0, szValue, -1, NULL, 0 );
644 szwValue = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
645 if( !szwValue)
646 goto end;
647 MultiByteToWideChar( CP_ACP, 0, szValue , -1, szwValue, len );
649 hr = MsiSetPropertyW( hInstall, szwName, szwValue);
651 end:
652 if( szwName )
653 HeapFree( GetProcessHeap(), 0, szwName );
654 if( szwValue )
655 HeapFree( GetProcessHeap(), 0, szwValue );
657 return hr;
660 UINT MSI_SetPropertyW( MSIPACKAGE *package, LPCWSTR szName, LPCWSTR szValue)
662 MSIQUERY *view;
663 MSIRECORD *row;
664 UINT rc;
665 DWORD sz = 0;
666 static const WCHAR Insert[]=
667 {'I','N','S','E','R','T',' ','i','n','t','o',' ','`','_','P','r','o','p'
668 ,'e','r','t','y','`',' ','(','`','_','P','r','o','p','e','r','t','y','`'
669 ,',','`','V','a','l','u','e','`',')',' ','V','A','L','U','E','S'
670 ,' ','(','?',')',0};
671 static const WCHAR Update[]=
672 {'U','P','D','A','T','E',' ','_','P','r','o','p','e'
673 ,'r','t','y',' ','s','e','t',' ','`','V','a','l','u','e','`',' ','='
674 ,' ','?',' ','w','h','e','r','e',' ','`','_','P','r','o','p'
675 ,'e','r','t','y','`',' ','=',' ','\'','%','s','\'',0};
676 WCHAR Query[1024];
678 TRACE("Setting property (%s %s)\n",debugstr_w(szName),
679 debugstr_w(szValue));
681 rc = MSI_GetPropertyW(package,szName,0,&sz);
682 if (rc==ERROR_MORE_DATA || rc == ERROR_SUCCESS)
684 sprintfW(Query,Update,szName);
686 row = MSI_CreateRecord(1);
687 MSI_RecordSetStringW(row,1,szValue);
690 else
692 strcpyW(Query,Insert);
694 row = MSI_CreateRecord(2);
695 MSI_RecordSetStringW(row,1,szName);
696 MSI_RecordSetStringW(row,2,szValue);
700 rc = MSI_DatabaseOpenViewW(package->db,Query,&view);
701 if (rc!= ERROR_SUCCESS)
703 msiobj_release(&row->hdr);
704 return rc;
707 rc = MSI_ViewExecute(view,row);
709 msiobj_release(&row->hdr);
710 MSI_ViewClose(view);
711 msiobj_release(&view->hdr);
713 return rc;
716 UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue)
718 MSIPACKAGE *package;
719 UINT ret;
721 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
722 if( !package)
723 return ERROR_INVALID_HANDLE;
724 ret = MSI_SetPropertyW( package, szName, szValue);
725 msiobj_release( &package->hdr );
726 return ret;
729 static UINT MSI_GetPropertyRow(MSIPACKAGE *package, LPCWSTR szName, MSIRECORD **row)
731 MSIQUERY *view;
732 UINT rc, sz;
733 static const WCHAR select[]=
734 {'s','e','l','e','c','t',' ','V','a','l','u','e',' ','f','r','o','m',' '
735 ,'_','P','r','o','p','e','r','t','y',' ','w','h','e','r','e',' '
736 ,'_','P','r','o','p','e','r','t','y','=','`','%','s','`',0};
737 LPWSTR query;
739 if (!szName)
740 return ERROR_INVALID_PARAMETER;
742 sz = sizeof select + strlenW(szName)*sizeof(WCHAR);
743 query = HeapAlloc(GetProcessHeap(), 0, sz);
744 sprintfW(query,select,szName);
746 rc = MSI_DatabaseOpenViewW(package->db, query, &view);
747 HeapFree(GetProcessHeap(), 0, query);
748 if (rc == ERROR_SUCCESS)
750 rc = MSI_ViewExecute(view, 0);
751 if (rc == ERROR_SUCCESS)
752 rc = MSI_ViewFetch(view,row);
754 MSI_ViewClose(view);
755 msiobj_release(&view->hdr);
758 return rc;
761 UINT MSI_GetPropertyW(MSIPACKAGE *package, LPCWSTR szName,
762 LPWSTR szValueBuf, DWORD* pchValueBuf)
764 MSIRECORD *row;
765 UINT rc;
767 rc = MSI_GetPropertyRow(package, szName, &row);
769 if (*pchValueBuf > 0)
770 szValueBuf[0] = 0;
772 if (rc == ERROR_SUCCESS)
774 rc = MSI_RecordGetStringW(row,1,szValueBuf,pchValueBuf);
775 msiobj_release(&row->hdr);
778 if (rc == ERROR_SUCCESS)
779 TRACE("returning %s for property %s\n", debugstr_w(szValueBuf),
780 debugstr_w(szName));
781 else if (rc == ERROR_MORE_DATA)
782 TRACE("need %li sized buffer for %s\n", *pchValueBuf,
783 debugstr_w(szName));
784 else
786 *pchValueBuf = 0;
787 TRACE("property not found\n");
790 return rc;
793 UINT MSI_GetPropertyA(MSIPACKAGE *package, LPCSTR szName,
794 LPSTR szValueBuf, DWORD* pchValueBuf)
796 MSIRECORD *row;
797 UINT rc, len;
798 LPWSTR szwName;
800 if (*pchValueBuf > 0)
801 szValueBuf[0] = 0;
803 len = MultiByteToWideChar( CP_ACP, 0, szName, -1, NULL, 0 );
804 szwName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
805 if (!szwName)
806 return ERROR_NOT_ENOUGH_MEMORY;
807 MultiByteToWideChar( CP_ACP, 0, szName, -1, szwName, len );
809 rc = MSI_GetPropertyRow(package, szwName, &row);
810 if (rc == ERROR_SUCCESS)
812 rc = MSI_RecordGetStringA(row,1,szValueBuf,pchValueBuf);
813 msiobj_release(&row->hdr);
816 if (rc == ERROR_SUCCESS)
817 TRACE("returning %s for property %s\n", debugstr_a(szValueBuf),
818 debugstr_a(szName));
819 else if (rc == ERROR_MORE_DATA)
820 TRACE("need %ld sized buffer for %s\n", *pchValueBuf,
821 debugstr_a(szName));
822 else
824 *pchValueBuf = 0;
825 TRACE("property not found\n");
827 HeapFree( GetProcessHeap(), 0, szwName );
829 return rc;
832 UINT WINAPI MsiGetPropertyA(MSIHANDLE hInstall, LPCSTR szName, LPSTR szValueBuf, DWORD* pchValueBuf)
834 MSIPACKAGE *package;
835 UINT ret;
837 TRACE("%lu %s %lu\n", hInstall, debugstr_a(szName), *pchValueBuf);
839 if (0 == hInstall)
840 return ERROR_INVALID_HANDLE;
841 if (NULL == szName)
842 return ERROR_INVALID_PARAMETER;
843 if (NULL != szValueBuf && NULL == pchValueBuf)
844 return ERROR_INVALID_PARAMETER;
846 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
847 if (!package)
848 return ERROR_INVALID_HANDLE;
849 ret = MSI_GetPropertyA(package, szName, szValueBuf, pchValueBuf );
850 msiobj_release( &package->hdr );
851 return ret;
855 UINT WINAPI MsiGetPropertyW(MSIHANDLE hInstall, LPCWSTR szName,
856 LPWSTR szValueBuf, DWORD* pchValueBuf)
858 MSIPACKAGE *package;
859 UINT ret;
861 if (0 == hInstall)
862 return ERROR_INVALID_HANDLE;
863 if (NULL == szName)
864 return ERROR_INVALID_PARAMETER;
865 if (NULL != szValueBuf && NULL == pchValueBuf)
866 return ERROR_INVALID_PARAMETER;
868 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
869 if (!package)
870 return ERROR_INVALID_HANDLE;
871 ret = MSI_GetPropertyW(package, szName, szValueBuf, pchValueBuf );
872 msiobj_release( &package->hdr );
873 return ret;