wined3d: Make sure volumes have memory allocated.
[wine] / dlls / msi / package.c
CommitLineData
eb0e0df9
AS
1/*
2 * Implementation of the Microsoft Installer (msi.dll)
3 *
4 * Copyright 2004 Aric Stewart for CodeWeavers
5 *
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.
10 *
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.
15 *
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
360a3f91 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
eb0e0df9
AS
19 */
20
21#define NONAMELESSUNION
9d90ef01 22#define NONAMELESSSTRUCT
eb0e0df9
AS
23
24#include <stdarg.h>
ed7c4bc8 25#include <stdio.h>
eb0e0df9
AS
26#include "windef.h"
27#include "winbase.h"
28#include "winreg.h"
29#include "winnls.h"
30#include "shlwapi.h"
2dd31728 31#include "wingdi.h"
eb0e0df9
AS
32#include "wine/debug.h"
33#include "msi.h"
34#include "msiquery.h"
eb0e0df9
AS
35#include "objidl.h"
36#include "wincrypt.h"
37#include "winuser.h"
d1617bea
JH
38#include "wininet.h"
39#include "urlmon.h"
eb0e0df9
AS
40#include "shlobj.h"
41#include "wine/unicode.h"
42#include "objbase.h"
f84fa0ce 43#include "msidefs.h"
8ae81d06 44#include "sddl.h"
eb0e0df9 45
828280f4 46#include "msipriv.h"
828280f4 47
eb0e0df9
AS
48WINE_DEFAULT_DEBUG_CHANNEL(msi);
49
a4fb1c94
MM
50static void msi_free_properties( MSIPACKAGE *package );
51
64de949c 52static void MSI_FreePackage( MSIOBJECTHDR *arg)
eb0e0df9 53{
a7a6f5f3 54 MSIPACKAGE *package= (MSIPACKAGE*) arg;
bdb29552 55
fd91013b
MM
56 if( package->dialog )
57 msi_dialog_destroy( package->dialog );
a4fb1c94 58
a7a6f5f3 59 msiobj_release( &package->db->hdr );
3c2e79e7
MM
60 ACTION_free_package_structures(package);
61 msi_free_properties( package );
eb0e0df9
AS
62}
63
0670ebc6
MM
64static UINT iterate_clone_props(MSIRECORD *row, LPVOID param)
65{
66 MSIPACKAGE *package = param;
67 LPCWSTR name, value;
68
69 name = MSI_RecordGetString( row, 1 );
70 value = MSI_RecordGetString( row, 2 );
71 MSI_SetPropertyW( package, name, value );
72
73 return ERROR_SUCCESS;
74}
75
a4fb1c94 76static UINT clone_properties( MSIPACKAGE *package )
eb0e0df9 77{
a7a6f5f3 78 static const WCHAR Query[] = {
0670ebc6
MM
79 'S','E','L','E','C','T',' ','*',' ',
80 'F','R','O','M',' ','`','P','r','o','p','e','r','t','y','`',0};
81 MSIQUERY *view = NULL;
82 UINT r;
eb0e0df9 83
0670ebc6
MM
84 r = MSI_OpenQuery( package->db, &view, Query );
85 if (r == ERROR_SUCCESS)
a7a6f5f3 86 {
0670ebc6 87 r = MSI_IterateRecords( view, NULL, iterate_clone_props, package );
a4fb1c94 88 msiobj_release(&view->hdr);
a7a6f5f3 89 }
0670ebc6 90 return r;
eb0e0df9
AS
91}
92
828280f4
MM
93/*
94 * set_installed_prop
95 *
96 * Sets the "Installed" property to indicate that
97 * the product is installed for the current user.
98 */
99static UINT set_installed_prop( MSIPACKAGE *package )
100{
101 static const WCHAR szInstalled[] = {
102 'I','n','s','t','a','l','l','e','d',0 };
103 WCHAR val[2] = { '1', 0 };
104 HKEY hkey = 0;
105 UINT r;
106
107 r = MSIREG_OpenUninstallKey( package->ProductCode, &hkey, FALSE );
108 if (r == ERROR_SUCCESS)
109 {
110 RegCloseKey( hkey );
111 MSI_SetPropertyW( package, szInstalled, val );
112 }
113
114 return r;
115}
116
8ae81d06
JH
117static UINT set_user_sid_prop( MSIPACKAGE *package )
118{
119 SID_NAME_USE use;
120 LPWSTR user_name;
0b652fe8 121 LPWSTR sid_str = NULL, dom = NULL;
8ae81d06
JH
122 DWORD size, dom_size;
123 PSID psid = NULL;
124 UINT r = ERROR_FUNCTION_FAILED;
125
126 static const WCHAR user_sid[] = {'U','s','e','r','S','I','D',0};
127
128 size = 0;
129 GetUserNameW( NULL, &size );
130
131 user_name = msi_alloc( (size + 1) * sizeof(WCHAR) );
132 if (!user_name)
133 return ERROR_OUTOFMEMORY;
134
135 if (!GetUserNameW( user_name, &size ))
136 goto done;
137
138 size = 0;
139 dom_size = 0;
140 LookupAccountNameW( NULL, user_name, NULL, &size, NULL, &dom_size, &use );
141
142 psid = msi_alloc( size );
8a38d303 143 dom = msi_alloc( dom_size*sizeof (WCHAR) );
8ae81d06
JH
144 if (!psid || !dom)
145 {
146 r = ERROR_OUTOFMEMORY;
147 goto done;
148 }
149
150 if (!LookupAccountNameW( NULL, user_name, psid, &size, dom, &dom_size, &use ))
151 goto done;
152
153 if (!ConvertSidToStringSidW( psid, &sid_str ))
154 goto done;
155
156 r = MSI_SetPropertyW( package, user_sid, sid_str );
157
158done:
159 LocalFree( sid_str );
160 msi_free( dom );
161 msi_free( psid );
162 msi_free( user_name );
163
164 return r;
165}
166
eb0e0df9
AS
167/*
168 * There are a whole slew of these we need to set
169 *
170 *
171http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/properties.asp
172 */
a7a6f5f3 173static VOID set_installer_properties(MSIPACKAGE *package)
eb0e0df9
AS
174{
175 WCHAR pth[MAX_PATH];
25955703 176 WCHAR *ptr;
7d3e5973 177 OSVERSIONINFOA OSVersion;
1fa2da07 178 MEMORYSTATUSEX msex;
7d3e5973 179 DWORD verval;
2dd31728
VL
180 WCHAR verstr[10], bufstr[20];
181 HDC dc;
08831b4a
JH
182 LPWSTR check;
183 HKEY hkey;
184 LONG res;
eb0e0df9
AS
185
186 static const WCHAR cszbs[]={'\\',0};
187 static const WCHAR CFF[] =
188{'C','o','m','m','o','n','F','i','l','e','s','F','o','l','d','e','r',0};
189 static const WCHAR PFF[] =
190{'P','r','o','g','r','a','m','F','i','l','e','s','F','o','l','d','e','r',0};
191 static const WCHAR CADF[] =
192{'C','o','m','m','o','n','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
6fae1ce6
VB
193 static const WCHAR FaF[] =
194{'F','a','v','o','r','i','t','e','s','F','o','l','d','e','r',0};
195 static const WCHAR FoF[] =
196{'F','o','n','t','s','F','o','l','d','e','r',0};
197 static const WCHAR SendTF[] =
198{'S','e','n','d','T','o','F','o','l','d','e','r',0};
199 static const WCHAR SMF[] =
200{'S','t','a','r','t','M','e','n','u','F','o','l','d','e','r',0};
201 static const WCHAR StF[] =
202{'S','t','a','r','t','u','p','F','o','l','d','e','r',0};
203 static const WCHAR TemplF[] =
204{'T','e','m','p','l','a','t','e','F','o','l','d','e','r',0};
205 static const WCHAR DF[] =
206{'D','e','s','k','t','o','p','F','o','l','d','e','r',0};
207 static const WCHAR PMF[] =
208{'P','r','o','g','r','a','m','M','e','n','u','F','o','l','d','e','r',0};
eb0e0df9
AS
209 static const WCHAR ATF[] =
210{'A','d','m','i','n','T','o','o','l','s','F','o','l','d','e','r',0};
211 static const WCHAR ADF[] =
212{'A','p','p','D','a','t','a','F','o','l','d','e','r',0};
213 static const WCHAR SF[] =
214{'S','y','s','t','e','m','F','o','l','d','e','r',0};
fb9d1194
AS
215 static const WCHAR SF16[] =
216{'S','y','s','t','e','m','1','6','F','o','l','d','e','r',0};
eb0e0df9
AS
217 static const WCHAR LADF[] =
218{'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
219 static const WCHAR MPF[] =
220{'M','y','P','i','c','t','u','r','e','s','F','o','l','d','e','r',0};
221 static const WCHAR PF[] =
222{'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0};
223 static const WCHAR WF[] =
224{'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
25955703
AS
225 static const WCHAR WV[] =
226{'W','i','n','d','o','w','s','V','o','l','u','m','e',0};
eb0e0df9
AS
227 static const WCHAR TF[]=
228{'T','e','m','p','F','o','l','d','e','r',0};
a7a6f5f3
AJ
229 static const WCHAR szAdminUser[] =
230{'A','d','m','i','n','U','s','e','r',0};
231 static const WCHAR szPriv[] =
232{'P','r','i','v','i','l','e','g','e','d',0};
233 static const WCHAR szOne[] =
234{'1',0};
235 static const WCHAR v9x[] = { 'V','e','r','s','i','o','n','9','X',0 };
236 static const WCHAR vNT[] = { 'V','e','r','s','i','o','n','N','T',0 };
237 static const WCHAR szFormat[] = {'%','l','i',0};
238 static const WCHAR szWinBuild[] =
239{'W','i','n','d','o','w','s','B','u','i','l','d', 0 };
240 static const WCHAR szSPL[] =
241{'S','e','r','v','i','c','e','P','a','c','k','L','e','v','e','l',0 };
242 static const WCHAR szSix[] = {'6',0 };
243
4104c622 244 static const WCHAR szVersionMsi[] = { 'V','e','r','s','i','o','n','M','s','i',0 };
1fa2da07 245 static const WCHAR szPhysicalMemory[] = { 'P','h','y','s','i','c','a','l','M','e','m','o','r','y',0 };
4104c622 246 static const WCHAR szFormat2[] = {'%','l','i','.','%','l','i',0};
671267a1
VL
247/* Screen properties */
248 static const WCHAR szScreenX[] = {'S','c','r','e','e','n','X',0};
249 static const WCHAR szScreenY[] = {'S','c','r','e','e','n','Y',0};
250 static const WCHAR szColorBits[] = {'C','o','l','o','r','B','i','t','s',0};
251 static const WCHAR szScreenFormat[] = {'%','d',0};
04a086ad 252 static const WCHAR szIntel[] = { 'I','n','t','e','l',0 };
c8548fb8 253 static const WCHAR szAllUsers[] = { 'A','L','L','U','S','E','R','S',0 };
08831b4a
JH
254 static const WCHAR szCurrentVersion[] = {
255 'S','O','F','T','W','A','R','E','\\',
256 'M','i','c','r','o','s','o','f','t','\\',
257 'W','i','n','d','o','w','s',' ','N','T','\\',
258 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',0
259 };
260 static const WCHAR szRegisteredUser[] = {'R','e','g','i','s','t','e','r','e','d','O','w','n','e','r',0};
261 static const WCHAR szRegisteredOrg[] = {
262 'R','e','g','i','s','t','e','r','e','d','O','r','g','a','n','i','z','a','t','i','o','n',0
263 };
264 static const WCHAR szUSERNAME[] = {'U','S','E','R','N','A','M','E',0};
265 static const WCHAR szCOMPANYNAME[] = {'C','O','M','P','A','N','Y','N','A','M','E',0};
04a086ad 266 SYSTEM_INFO sys_info;
4104c622 267
828280f4
MM
268 /*
269 * Other things that probably should be set:
270 *
271 * SystemLanguageID ComputerName UserLanguageID LogonUser VirtualMemory
272 * Intel ShellAdvSupport DefaultUIFont VersionDatabase PackagecodeChanging
273 * ProductState CaptionHeight BorderTop BorderSide TextHeight
274 * RedirectedDllSupport Time Date Privileged
275 */
eb0e0df9
AS
276
277 SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES_COMMON,NULL,0,pth);
278 strcatW(pth,cszbs);
a7a6f5f3 279 MSI_SetPropertyW(package, CFF, pth);
eb0e0df9
AS
280
281 SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES,NULL,0,pth);
282 strcatW(pth,cszbs);
a7a6f5f3 283 MSI_SetPropertyW(package, PFF, pth);
eb0e0df9
AS
284
285 SHGetFolderPathW(NULL,CSIDL_COMMON_APPDATA,NULL,0,pth);
286 strcatW(pth,cszbs);
a7a6f5f3 287 MSI_SetPropertyW(package, CADF, pth);
eb0e0df9 288
6fae1ce6
VB
289 SHGetFolderPathW(NULL,CSIDL_FAVORITES,NULL,0,pth);
290 strcatW(pth,cszbs);
291 MSI_SetPropertyW(package, FaF, pth);
292
293 SHGetFolderPathW(NULL,CSIDL_FONTS,NULL,0,pth);
294 strcatW(pth,cszbs);
295 MSI_SetPropertyW(package, FoF, pth);
296
297 SHGetFolderPathW(NULL,CSIDL_SENDTO,NULL,0,pth);
298 strcatW(pth,cszbs);
299 MSI_SetPropertyW(package, SendTF, pth);
300
301 SHGetFolderPathW(NULL,CSIDL_STARTMENU,NULL,0,pth);
302 strcatW(pth,cszbs);
303 MSI_SetPropertyW(package, SMF, pth);
304
305 SHGetFolderPathW(NULL,CSIDL_STARTUP,NULL,0,pth);
306 strcatW(pth,cszbs);
307 MSI_SetPropertyW(package, StF, pth);
308
309 SHGetFolderPathW(NULL,CSIDL_TEMPLATES,NULL,0,pth);
310 strcatW(pth,cszbs);
311 MSI_SetPropertyW(package, TemplF, pth);
312
313 SHGetFolderPathW(NULL,CSIDL_DESKTOP,NULL,0,pth);
314 strcatW(pth,cszbs);
315 MSI_SetPropertyW(package, DF, pth);
316
317 SHGetFolderPathW(NULL,CSIDL_PROGRAMS,NULL,0,pth);
318 strcatW(pth,cszbs);
319 MSI_SetPropertyW(package, PMF, pth);
320
eb0e0df9
AS
321 SHGetFolderPathW(NULL,CSIDL_ADMINTOOLS,NULL,0,pth);
322 strcatW(pth,cszbs);
a7a6f5f3 323 MSI_SetPropertyW(package, ATF, pth);
eb0e0df9
AS
324
325 SHGetFolderPathW(NULL,CSIDL_APPDATA,NULL,0,pth);
326 strcatW(pth,cszbs);
a7a6f5f3 327 MSI_SetPropertyW(package, ADF, pth);
eb0e0df9
AS
328
329 SHGetFolderPathW(NULL,CSIDL_SYSTEM,NULL,0,pth);
330 strcatW(pth,cszbs);
a7a6f5f3 331 MSI_SetPropertyW(package, SF, pth);
fb9d1194 332 MSI_SetPropertyW(package, SF16, pth);
eb0e0df9
AS
333
334 SHGetFolderPathW(NULL,CSIDL_LOCAL_APPDATA,NULL,0,pth);
335 strcatW(pth,cszbs);
a7a6f5f3 336 MSI_SetPropertyW(package, LADF, pth);
eb0e0df9
AS
337
338 SHGetFolderPathW(NULL,CSIDL_MYPICTURES,NULL,0,pth);
339 strcatW(pth,cszbs);
a7a6f5f3 340 MSI_SetPropertyW(package, MPF, pth);
eb0e0df9
AS
341
342 SHGetFolderPathW(NULL,CSIDL_PERSONAL,NULL,0,pth);
343 strcatW(pth,cszbs);
a7a6f5f3 344 MSI_SetPropertyW(package, PF, pth);
eb0e0df9
AS
345
346 SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
347 strcatW(pth,cszbs);
a7a6f5f3 348 MSI_SetPropertyW(package, WF, pth);
1fa2da07
MM
349
350 /* Physical Memory is specified in MB. Using total amount. */
351 msex.dwLength = sizeof(msex);
352 GlobalMemoryStatusEx( &msex );
353 sprintfW( bufstr, szScreenFormat, (int)(msex.ullTotalPhys/1024/1024));
354 MSI_SetPropertyW(package, szPhysicalMemory, bufstr);
eb0e0df9 355
25955703
AS
356 SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
357 ptr = strchrW(pth,'\\');
358 if (ptr)
74ad0d3a 359 *(ptr+1) = 0;
25955703
AS
360 MSI_SetPropertyW(package, WV, pth);
361
eb0e0df9 362 GetTempPathW(MAX_PATH,pth);
a7a6f5f3 363 MSI_SetPropertyW(package, TF, pth);
7d3e5973 364
2cf222f9 365
a7a6f5f3
AJ
366 /* in a wine environment the user is always admin and privileged */
367 MSI_SetPropertyW(package,szAdminUser,szOne);
368 MSI_SetPropertyW(package,szPriv,szOne);
c8548fb8 369 MSI_SetPropertyW(package, szAllUsers, szOne);
7d3e5973
AS
370
371 /* set the os things */
372 OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
373 GetVersionExA(&OSVersion);
374 verval = OSVersion.dwMinorVersion+OSVersion.dwMajorVersion*100;
a7a6f5f3 375 sprintfW(verstr,szFormat,verval);
7d3e5973
AS
376 switch (OSVersion.dwPlatformId)
377 {
378 case VER_PLATFORM_WIN32_WINDOWS:
a7a6f5f3 379 MSI_SetPropertyW(package,v9x,verstr);
7d3e5973
AS
380 break;
381 case VER_PLATFORM_WIN32_NT:
a7a6f5f3 382 MSI_SetPropertyW(package,vNT,verstr);
7d3e5973
AS
383 break;
384 }
a7a6f5f3
AJ
385 sprintfW(verstr,szFormat,OSVersion.dwBuildNumber);
386 MSI_SetPropertyW(package,szWinBuild,verstr);
7d3e5973 387 /* just fudge this */
a7a6f5f3 388 MSI_SetPropertyW(package,szSPL,szSix);
eb0e0df9 389
2dd31728
VL
390 sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION);
391 MSI_SetPropertyW( package, szVersionMsi, bufstr );
392
04a086ad 393 GetSystemInfo( &sys_info );
9d90ef01 394 if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
04a086ad
MM
395 {
396 sprintfW( bufstr, szScreenFormat, sys_info.wProcessorLevel );
397 MSI_SetPropertyW( package, szIntel, bufstr );
398 }
399
2dd31728
VL
400 /* Screen properties. */
401 dc = GetDC(0);
402 sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, HORZRES ) );
403 MSI_SetPropertyW( package, szScreenX, bufstr );
404 sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, VERTRES ));
405 MSI_SetPropertyW( package, szScreenY, bufstr );
406 sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, BITSPIXEL ));
407 MSI_SetPropertyW( package, szColorBits, bufstr );
408 ReleaseDC(0, dc);
08831b4a
JH
409
410 /* USERNAME and COMPANYNAME */
411 res = RegOpenKeyW( HKEY_LOCAL_MACHINE, szCurrentVersion, &hkey );
412 if (res != ERROR_SUCCESS)
413 return;
414
415 check = msi_dup_property( package, szUSERNAME );
416 if (!check)
417 {
418 LPWSTR user = msi_reg_get_val_str( hkey, szRegisteredUser );
419 MSI_SetPropertyW( package, szUSERNAME, user );
420 msi_free( user );
421 }
422
423 msi_free( check );
424
425 check = msi_dup_property( package, szCOMPANYNAME );
426 if (!check)
427 {
428 LPWSTR company = msi_reg_get_val_str( hkey, szRegisteredOrg );
429 MSI_SetPropertyW( package, szCOMPANYNAME, company );
430 msi_free( company );
431 }
432
8ae81d06
JH
433 if ( set_user_sid_prop( package ) != ERROR_SUCCESS)
434 ERR("Failed to set the UserSID property\n");
435
08831b4a
JH
436 msi_free( check );
437 CloseHandle( hkey );
2cf222f9 438}
eb0e0df9 439
f84fa0ce
JH
440static UINT msi_get_word_count( MSIPACKAGE *package )
441{
442 UINT rc;
443 INT word_count;
444 MSIHANDLE suminfo;
445 MSIHANDLE hdb = alloc_msihandle( &package->db->hdr );
446
337e1e20
DK
447 if (!hdb) {
448 ERR("Unable to allocate handle\n");
449 return 0;
450 }
f84fa0ce
JH
451 rc = MsiGetSummaryInformationW( hdb, NULL, 0, &suminfo );
452 MsiCloseHandle(hdb);
453 if (rc != ERROR_SUCCESS)
454 {
455 ERR("Unable to open Summary Information\n");
456 return 0;
457 }
458
459 rc = MsiSummaryInfoGetPropertyW( suminfo, PID_WORDCOUNT, NULL,
460 &word_count, NULL, NULL, NULL );
461 if (rc != ERROR_SUCCESS)
462 {
463 ERR("Unable to query word count\n");
464 MsiCloseHandle(suminfo);
465 return 0;
466 }
467
468 MsiCloseHandle(suminfo);
469 return word_count;
470}
471
eadf2f82 472static MSIPACKAGE *msi_alloc_package( void )
eb0e0df9 473{
eadf2f82 474 MSIPACKAGE *package;
a4fb1c94 475 int i;
eb0e0df9 476
a7a6f5f3
AJ
477 package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE),
478 MSI_FreePackage );
279ef156 479 if( package )
eb0e0df9 480 {
38d67a45 481 list_init( &package->components );
979511fe 482 list_init( &package->features );
e18f8abe 483 list_init( &package->files );
c50ef541 484 list_init( &package->tempfiles );
979511fe 485 list_init( &package->folders );
b402f048 486 list_init( &package->subscriptions );
febad089 487 list_init( &package->appids );
a391a98a 488 list_init( &package->classes );
9e558d74 489 list_init( &package->mimes );
0c49c1c4 490 list_init( &package->extensions );
1ceb25ba 491 list_init( &package->progids );
0232c5c4 492 list_init( &package->RunningActions );
a7a6f5f3 493
eadf2f82
MM
494 for (i=0; i<PROPERTY_HASH_SIZE; i++)
495 list_init( &package->props[i] );
496
497 package->ActionFormat = NULL;
498 package->LastAction = NULL;
499 package->dialog = NULL;
500 package->next_dialog = NULL;
501 }
502
503 return package;
504}
505
506MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPWSTR base_url )
507{
508 static const WCHAR szLevel[] = { 'U','I','L','e','v','e','l',0 };
509 static const WCHAR szpi[] = {'%','i',0};
510 static const WCHAR szProductCode[] = {
511 'P','r','o','d','u','c','t','C','o','d','e',0};
512 MSIPACKAGE *package;
513 WCHAR uilevel[10];
514
515 TRACE("%p\n", db);
516
517 package = msi_alloc_package();
518 if (package)
519 {
520 msiobj_addref( &db->hdr );
521 package->db = db;
522
f84fa0ce 523 package->WordCount = msi_get_word_count( package );
c5075435 524 package->PackagePath = strdupW( db->path );
ae18c2dc 525 package->BaseURL = strdupW( base_url );
f84fa0ce 526
a4fb1c94 527 clone_properties( package );
a7a6f5f3 528 set_installer_properties(package);
a7a6f5f3
AJ
529 sprintfW(uilevel,szpi,gUILevel);
530 MSI_SetPropertyW(package, szLevel, uilevel);
828280f4
MM
531
532 package->ProductCode = msi_dup_property( package, szProductCode );
533 set_installed_prop( package );
eb0e0df9
AS
534 }
535
479213c4 536 return package;
279ef156
MM
537}
538
786920b7
MM
539/*
540 * copy_package_to_temp [internal]
541 *
542 * copy the msi file to a temp file to prevent locking a CD
543 * with a multi disc install
544 *
545 * FIXME: I think this is wrong, and instead of copying the package,
546 * we should read all the tables to memory, then open the
547 * database to read binary streams on demand.
548 */
549static LPCWSTR copy_package_to_temp( LPCWSTR szPackage, LPWSTR filename )
550{
551 WCHAR path[MAX_PATH];
032b1389 552 static const WCHAR szMSI[] = {'m','s','i',0};
786920b7
MM
553
554 GetTempPathW( MAX_PATH, path );
555 GetTempFileNameW( path, szMSI, 0, filename );
556
557 if( !CopyFileW( szPackage, filename, FALSE ) )
558 {
032b1389 559 DeleteFileW( filename );
4a7bb647 560 ERR("failed to copy package %s\n", debugstr_w(szPackage) );
786920b7
MM
561 return szPackage;
562 }
563
564 TRACE("Opening relocated package %s\n", debugstr_w( filename ));
565 return filename;
566}
567
1ff96c63 568LPCWSTR msi_download_file( LPCWSTR szUrl, LPWSTR filename )
d1617bea
JH
569{
570 LPINTERNET_CACHE_ENTRY_INFOW cache_entry;
571 DWORD size = 0;
572 HRESULT hr;
573
574 /* call will always fail, becase size is 0,
575 * but will return ERROR_FILE_NOT_FOUND first
576 * if the file doesn't exist
577 */
578 GetUrlCacheEntryInfoW( szUrl, NULL, &size );
579 if ( GetLastError() != ERROR_FILE_NOT_FOUND )
580 {
581 cache_entry = HeapAlloc( GetProcessHeap(), 0, size );
582 if ( !GetUrlCacheEntryInfoW( szUrl, cache_entry, &size ) )
583 {
584 HeapFree( GetProcessHeap(), 0, cache_entry );
585 return szUrl;
586 }
587
588 lstrcpyW( filename, cache_entry->lpszLocalFileName );
589 HeapFree( GetProcessHeap(), 0, cache_entry );
590 return filename;
591 }
592
593 hr = URLDownloadToCacheFileW( NULL, szUrl, filename, MAX_PATH, 0, NULL );
594 if ( FAILED(hr) )
595 return szUrl;
596
597 return filename;
598}
599
279ef156
MM
600UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
601{
3c2e79e7
MM
602 static const WCHAR OriginalDatabase[] =
603 {'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
604 static const WCHAR Database[] = {'D','A','T','A','B','A','S','E',0};
279ef156 605 MSIDATABASE *db = NULL;
479213c4 606 MSIPACKAGE *package;
279ef156 607 MSIHANDLE handle;
ae18c2dc 608 LPWSTR ptr, base_url = NULL;
786920b7 609 UINT r;
3c2e79e7
MM
610 WCHAR temppath[MAX_PATH];
611 LPCWSTR file = szPackage;
da14a4a2 612
279ef156
MM
613 TRACE("%s %p\n", debugstr_w(szPackage), pPackage);
614
615 if( szPackage[0] == '#' )
616 {
617 handle = atoiW(&szPackage[1]);
618 db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE );
619 if( !db )
620 return ERROR_INVALID_HANDLE;
621 }
622 else
623 {
d1617bea 624 if ( UrlIsW( szPackage, URLIS_URL ) )
ae18c2dc 625 {
1ff96c63 626 file = msi_download_file( szPackage, temppath );
ae18c2dc
JH
627
628 base_url = strdupW( szPackage );
629 if ( !base_url )
630 return ERROR_OUTOFMEMORY;
631
632 ptr = strrchrW( base_url, '/' );
633 if (ptr) *(ptr + 1) = '\0';
634 }
d1617bea
JH
635 else
636 file = copy_package_to_temp( szPackage, temppath );
786920b7
MM
637
638 r = MSI_OpenDatabaseW( file, MSIDBOPEN_READONLY, &db );
479213c4 639 if( r != ERROR_SUCCESS )
fb7646be
JH
640 {
641 if (GetLastError() == ERROR_FILE_NOT_FOUND)
642 msi_ui_error( 4, MB_OK | MB_ICONWARNING );
3c2e79e7
MM
643 if (file != szPackage)
644 DeleteFileW( file );
fb7646be 645
479213c4 646 return r;
fb7646be 647 }
279ef156
MM
648 }
649
ae18c2dc
JH
650 package = MSI_CreatePackage( db, base_url );
651 msi_free( base_url );
479213c4
MM
652 msiobj_release( &db->hdr );
653 if( !package )
3c2e79e7
MM
654 {
655 if (file != szPackage)
656 DeleteFileW( file );
479213c4 657 return ERROR_FUNCTION_FAILED;
3c2e79e7
MM
658 }
659
660 if( file != szPackage )
661 track_tempfile( package, file );
279ef156 662
479213c4 663 if( szPackage[0] != '#' )
279ef156 664 {
479213c4
MM
665 MSI_SetPropertyW( package, OriginalDatabase, szPackage );
666 MSI_SetPropertyW( package, Database, szPackage );
279ef156 667 }
da14a4a2
JH
668 else
669 {
670 MSI_SetPropertyW( package, OriginalDatabase, db->path );
671 MSI_SetPropertyW( package, Database, db->path );
672 }
279ef156 673
479213c4 674 *pPackage = package;
eb0e0df9 675
479213c4 676 return ERROR_SUCCESS;
a7a6f5f3 677}
eb0e0df9 678
279ef156 679UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
a7a6f5f3
AJ
680{
681 MSIPACKAGE *package = NULL;
682 UINT ret;
eb0e0df9 683
f1d4646a 684 TRACE("%s %08x %p\n", debugstr_w(szPackage), dwOptions, phPackage );
279ef156 685
a92fe55c
MM
686 if( szPackage == NULL )
687 return ERROR_INVALID_PARAMETER;
688
279ef156 689 if( dwOptions )
f1d4646a 690 FIXME("dwOptions %08x not supported\n", dwOptions);
279ef156 691
786920b7 692 ret = MSI_OpenPackageW( szPackage, &package );
a7a6f5f3
AJ
693 if( ret == ERROR_SUCCESS )
694 {
695 *phPackage = alloc_msihandle( &package->hdr );
337e1e20
DK
696 if (! *phPackage)
697 ret = ERROR_NOT_ENOUGH_MEMORY;
a7a6f5f3
AJ
698 msiobj_release( &package->hdr );
699 }
f1b52aef 700
a7a6f5f3 701 return ret;
eb0e0df9
AS
702}
703
279ef156
MM
704UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
705{
706 return MsiOpenPackageExW( szPackage, 0, phPackage );
707}
708
eb0e0df9
AS
709UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
710{
279ef156 711 LPWSTR szwPack = NULL;
77a19ed8 712 UINT ret;
279ef156
MM
713
714 if( szPackage )
715 {
77a19ed8
MM
716 szwPack = strdupAtoW( szPackage );
717 if( !szwPack )
718 return ERROR_OUTOFMEMORY;
279ef156
MM
719 }
720
721 ret = MsiOpenPackageExW( szwPack, dwOptions, phPackage );
722
8dc28d53 723 msi_free( szwPack );
279ef156
MM
724
725 return ret;
eb0e0df9
AS
726}
727
279ef156 728UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
eb0e0df9 729{
279ef156 730 return MsiOpenPackageExA( szPackage, 0, phPackage );
eb0e0df9
AS
731}
732
733MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
734{
735 MSIPACKAGE *package;
a7a6f5f3 736 MSIHANDLE handle = 0;
eb0e0df9 737
6e2bca34 738 TRACE("(%ld)\n",hInstall);
eb0e0df9
AS
739
740 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
a7a6f5f3
AJ
741 if( package)
742 {
743 handle = alloc_msihandle( &package->db->hdr );
744 msiobj_release( &package->hdr );
745 }
eb0e0df9 746
a7a6f5f3 747 return handle;
eb0e0df9
AS
748}
749
a7a6f5f3
AJ
750INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType,
751 MSIRECORD *record)
eb0e0df9 752{
d679bc5a
RS
753 static const WCHAR szActionData[] =
754 {'A','c','t','i','o','n','D','a','t','a',0};
755 static const WCHAR szSetProgress[] =
756 {'S','e','t','P','r','o','g','r','e','s','s',0};
757 static const WCHAR szActionText[] =
758 {'A','c','t','i','o','n','T','e','x','t',0};
2e9b5f7c 759 DWORD log_type = 0;
a7a6f5f3 760 LPWSTR message;
2e9b5f7c 761 DWORD sz;
bdb29552 762 DWORD total_size = 0;
bdb29552 763 INT i;
7231a439 764 INT rc;
a7a6f5f3
AJ
765 char *msg;
766 int len;
7231a439 767
0edbaf7e 768 TRACE("%x\n", eMessageType);
7231a439 769 rc = 0;
2e9b5f7c
AS
770
771 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ERROR)
772 log_type |= INSTALLLOGMODE_ERROR;
773 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_WARNING)
774 log_type |= INSTALLLOGMODE_WARNING;
775 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_USER)
776 log_type |= INSTALLLOGMODE_USER;
777 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INFO)
778 log_type |= INSTALLLOGMODE_INFO;
779 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA)
780 log_type |= INSTALLLOGMODE_COMMONDATA;
781 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART)
2e9b5f7c 782 log_type |= INSTALLLOGMODE_ACTIONSTART;
2e9b5f7c
AS
783 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONDATA)
784 log_type |= INSTALLLOGMODE_ACTIONDATA;
7d3e5973
AS
785 /* just a guess */
786 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_PROGRESS)
787 log_type |= 0x800;
2e9b5f7c 788
d679bc5a
RS
789 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART)
790 {
791 static const WCHAR template_s[]=
e1fdf3e2 792 {'A','c','t','i','o','n',' ','%','s',':',' ','%','s','.',' ',0};
d679bc5a
RS
793 static const WCHAR format[] =
794 {'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0};
795 WCHAR timet[0x100];
e1fdf3e2
MM
796 LPCWSTR action_text, action;
797 LPWSTR deformatted = NULL;
d679bc5a
RS
798
799 GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, format, timet, 0x100);
800
801 action = MSI_RecordGetString(record, 1);
802 action_text = MSI_RecordGetString(record, 2);
f10365bb
JH
803
804 if (!action || !action_text)
805 return IDOK;
806
e1fdf3e2
MM
807 deformat_string(package, action_text, &deformatted);
808
809 len = strlenW(timet) + strlenW(action) + strlenW(template_s);
810 if (deformatted)
811 len += strlenW(deformatted);
812 message = msi_alloc(len*sizeof(WCHAR));
813 sprintfW(message, template_s, timet, action);
814 if (deformatted)
815 strcatW(message, deformatted);
816 msi_free(deformatted);
d679bc5a
RS
817 }
818 else
bdb29552 819 {
d679bc5a
RS
820 INT msg_field=1;
821 message = msi_alloc(1*sizeof (WCHAR));
822 message[0]=0;
823 msg_field = MSI_RecordGetFieldCount(record);
824 for (i = 1; i <= msg_field; i++)
bdb29552 825 {
d679bc5a
RS
826 LPWSTR tmp;
827 WCHAR number[3];
828 static const WCHAR format[] = { '%','i',':',' ',0};
829 static const WCHAR space[] = { ' ',0};
830 sz = 0;
831 MSI_RecordGetStringW(record,i,NULL,&sz);
832 sz+=4;
833 total_size+=sz*sizeof(WCHAR);
834 tmp = msi_alloc(sz*sizeof(WCHAR));
835 message = msi_realloc(message,total_size*sizeof (WCHAR));
836
837 MSI_RecordGetStringW(record,i,tmp,&sz);
838
839 if (msg_field > 1)
840 {
841 sprintfW(number,format,i);
842 strcatW(message,number);
843 }
844 strcatW(message,tmp);
845 if (msg_field > 1)
846 strcatW(message,space);
847
848 msi_free(tmp);
bdb29552 849 }
bdb29552
AS
850 }
851
f1d4646a 852 TRACE("(%p %x %x %s)\n", gUIHandlerA, gUIFilter, log_type,
a7a6f5f3
AJ
853 debugstr_w(message));
854
855 /* convert it to ASCII */
856 len = WideCharToMultiByte( CP_ACP, 0, message, -1,
857 NULL, 0, NULL, NULL );
8dc28d53 858 msg = msi_alloc( len );
a7a6f5f3
AJ
859 WideCharToMultiByte( CP_ACP, 0, message, -1,
860 msg, len, NULL, NULL );
2e9b5f7c 861
ee4f4a05 862 if (gUIHandlerA && (gUIFilter & log_type))
a7a6f5f3 863 {
ee4f4a05 864 rc = gUIHandlerA(gUIContext,eMessageType,msg);
a7a6f5f3 865 }
7231a439
AS
866
867 if ((!rc) && (gszLogFile[0]) && !((eMessageType & 0xff000000) ==
868 INSTALLMESSAGE_PROGRESS))
869 {
870 DWORD write;
871 HANDLE log_file = CreateFileW(gszLogFile,GENERIC_WRITE, 0, NULL,
872 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2e9b5f7c 873
7231a439
AS
874 if (log_file != INVALID_HANDLE_VALUE)
875 {
876 SetFilePointer(log_file,0, NULL, FILE_END);
a7a6f5f3 877 WriteFile(log_file,msg,strlen(msg),&write,NULL);
7231a439
AS
878 WriteFile(log_file,"\n",1,&write,NULL);
879 CloseHandle(log_file);
880 }
881 }
8dc28d53 882 msi_free( msg );
d679bc5a 883
8dc28d53 884 msi_free( message);
d679bc5a
RS
885
886 switch (eMessageType & 0xff000000)
887 {
888 case INSTALLMESSAGE_ACTIONDATA:
889 /* FIXME: format record here instead of in ui_actiondata to get the
890 * correct action data for external scripts */
891 ControlEvent_FireSubscribedEvent(package, szActionData, record);
892 break;
893 case INSTALLMESSAGE_ACTIONSTART:
894 {
895 MSIRECORD *uirow;
896 LPWSTR deformated;
897 LPCWSTR action_text = MSI_RecordGetString(record, 2);
898
899 deformat_string(package, action_text, &deformated);
900 uirow = MSI_CreateRecord(1);
901 MSI_RecordSetStringW(uirow, 1, deformated);
902 TRACE("INSTALLMESSAGE_ACTIONSTART: %s\n", debugstr_w(deformated));
903 msi_free(deformated);
904
905 ControlEvent_FireSubscribedEvent(package, szActionText, uirow);
906
907 msiobj_release(&uirow->hdr);
908 break;
909 }
910 case INSTALLMESSAGE_PROGRESS:
911 ControlEvent_FireSubscribedEvent(package, szSetProgress, record);
912 break;
913 }
914
eb0e0df9
AS
915 return ERROR_SUCCESS;
916}
917
a7a6f5f3
AJ
918INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
919 MSIHANDLE hRecord)
920{
921 UINT ret = ERROR_INVALID_HANDLE;
922 MSIPACKAGE *package = NULL;
923 MSIRECORD *record = NULL;
924
925 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
926 if( !package )
5ebd4e93 927 return ERROR_INVALID_HANDLE;
a7a6f5f3
AJ
928
929 record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD );
930 if( !record )
931 goto out;
932
933 ret = MSI_ProcessMessage( package, eMessageType, record );
934
935out:
5ebd4e93 936 msiobj_release( &package->hdr );
a7a6f5f3
AJ
937 if( record )
938 msiobj_release( &record->hdr );
939
940 return ret;
941}
942
eb0e0df9 943/* property code */
a4fb1c94
MM
944
945typedef struct msi_property {
946 struct list entry;
947 LPWSTR key;
948 LPWSTR value;
949} msi_property;
950
951static UINT msi_prop_makehash( const WCHAR *str )
952{
953 UINT hash = 0;
954
955 if (str==NULL)
956 return hash;
957
958 while( *str )
959 {
b1839561 960 hash ^= *str++;
a4fb1c94
MM
961 hash *= 53;
962 hash = (hash<<5) | (hash>>27);
963 }
964 return hash % PROPERTY_HASH_SIZE;
965}
966
967static msi_property *msi_prop_find( MSIPACKAGE *package, LPCWSTR key )
968{
969 UINT hash = msi_prop_makehash( key );
970 msi_property *prop;
971
972 LIST_FOR_EACH_ENTRY( prop, &package->props[hash], msi_property, entry )
b1839561 973 if (!lstrcmpW( prop->key, key ))
a4fb1c94
MM
974 return prop;
975 return NULL;
976}
977
978static msi_property *msi_prop_add( MSIPACKAGE *package, LPCWSTR key )
979{
980 UINT hash = msi_prop_makehash( key );
981 msi_property *prop;
982
983 prop = msi_alloc( sizeof *prop );
984 if (prop)
985 {
986 prop->key = strdupW( key );
987 prop->value = NULL;
988 list_add_head( &package->props[hash], &prop->entry );
989 }
990 return prop;
991}
992
993static void msi_delete_property( msi_property *prop )
994{
995 list_remove( &prop->entry );
996 msi_free( prop->key );
997 msi_free( prop->value );
998 msi_free( prop );
999}
1000
1001static void msi_free_properties( MSIPACKAGE *package )
1002{
1003 int i;
1004
1005 for ( i=0; i<PROPERTY_HASH_SIZE; i++ )
1006 {
1007 while ( !list_empty(&package->props[i]) )
1008 {
1009 msi_property *prop;
1010 prop = LIST_ENTRY( list_head( &package->props[i] ),
1011 msi_property, entry );
1012 msi_delete_property( prop );
1013 }
1014 }
1015}
1016
3e6f31bf 1017UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue )
eb0e0df9
AS
1018{
1019 LPWSTR szwName = NULL, szwValue = NULL;
3e6f31bf 1020 UINT r = ERROR_OUTOFMEMORY;
eb0e0df9 1021
3e6f31bf
MM
1022 szwName = strdupAtoW( szName );
1023 if( szName && !szwName )
1024 goto end;
eb0e0df9 1025
3e6f31bf
MM
1026 szwValue = strdupAtoW( szValue );
1027 if( szValue && !szwValue )
1028 goto end;
eb0e0df9 1029
3e6f31bf 1030 r = MsiSetPropertyW( hInstall, szwName, szwValue);
eb0e0df9
AS
1031
1032end:
8dc28d53
MM
1033 msi_free( szwName );
1034 msi_free( szwValue );
eb0e0df9 1035
3e6f31bf 1036 return r;
eb0e0df9
AS
1037}
1038
a7a6f5f3 1039UINT MSI_SetPropertyW( MSIPACKAGE *package, LPCWSTR szName, LPCWSTR szValue)
eb0e0df9 1040{
a4fb1c94 1041 msi_property *prop;
eb0e0df9 1042
3e6f31bf
MM
1043 TRACE("%p %s %s\n", package, debugstr_w(szName), debugstr_w(szValue));
1044
1045 if (!szName)
1046 return ERROR_INVALID_PARAMETER;
1047
f4c0524e 1048 /* this one is weird... */
3e6f31bf
MM
1049 if (!szName[0])
1050 return szValue ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS;
eb0e0df9 1051
a4fb1c94
MM
1052 prop = msi_prop_find( package, szName );
1053 if (!prop)
1054 prop = msi_prop_add( package, szName );
eb0e0df9 1055
a4fb1c94
MM
1056 if (!prop)
1057 return ERROR_OUTOFMEMORY;
eb0e0df9 1058
a4fb1c94 1059 if (szValue)
2e9b5f7c 1060 {
a4fb1c94
MM
1061 msi_free( prop->value );
1062 prop->value = strdupW( szValue );
744e22c7 1063 }
a4fb1c94
MM
1064 else
1065 msi_delete_property( prop );
eb0e0df9 1066
a4fb1c94 1067 return ERROR_SUCCESS;
eb0e0df9
AS
1068}
1069
a7a6f5f3
AJ
1070UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue)
1071{
1072 MSIPACKAGE *package;
1073 UINT ret;
1074
1075 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
77a19ed8 1076 if( !package )
a7a6f5f3
AJ
1077 return ERROR_INVALID_HANDLE;
1078 ret = MSI_SetPropertyW( package, szName, szValue);
1079 msiobj_release( &package->hdr );
1080 return ret;
1081}
1082
3e6f31bf
MM
1083/* internal function, not compatible with MsiGetPropertyW */
1084UINT MSI_GetPropertyW( MSIPACKAGE *package, LPCWSTR szName,
1085 LPWSTR szValueBuf, DWORD* pchValueBuf )
eb0e0df9 1086{
a4fb1c94
MM
1087 msi_property *prop;
1088 UINT r, len;
62cd1e03
AS
1089
1090 if (*pchValueBuf > 0)
1091 szValueBuf[0] = 0;
1092
a4fb1c94
MM
1093 prop = msi_prop_find( package, szName );
1094 if (!prop)
181705cb 1095 {
a4fb1c94
MM
1096 *pchValueBuf = 0;
1097 TRACE("property %s not found\n", debugstr_w(szName));
1098 return ERROR_FUNCTION_FAILED;
eb0e0df9
AS
1099 }
1100
a4fb1c94
MM
1101 if (prop->value)
1102 {
1103 len = lstrlenW( prop->value );
1104 lstrcpynW(szValueBuf, prop->value, *pchValueBuf);
1105 }
181705cb 1106 else
eb0e0df9 1107 {
a4fb1c94
MM
1108 len = 1;
1109 if( *pchValueBuf > 0 )
1110 szValueBuf[0] = 0;
181705cb 1111 }
eb0e0df9 1112
a4fb1c94
MM
1113 TRACE("%s -> %s\n", debugstr_w(szName), debugstr_w(szValueBuf));
1114
1115 if ( *pchValueBuf <= len )
1116 {
f1d4646a 1117 TRACE("have %u, need %u -> ERROR_MORE_DATA\n", *pchValueBuf, len);
a4fb1c94
MM
1118 r = ERROR_MORE_DATA;
1119 }
1120 else
1121 r = ERROR_SUCCESS;
1122
1123 *pchValueBuf = len;
1124
1125 return r;
181705cb
MM
1126}
1127
8ebbc8c0
MM
1128LPWSTR msi_dup_property( MSIPACKAGE *package, LPCWSTR szName )
1129{
1130 msi_property *prop;
1131 LPWSTR value = NULL;
1132
1133 prop = msi_prop_find( package, szName );
1134 if (prop)
1135 value = strdupW( prop->value );
1136
1137 return value;
1138}
1139
1140int msi_get_property_int( MSIPACKAGE *package, LPCWSTR name, int value )
1141{
1142 msi_property *prop;
1143
1144 prop = msi_prop_find( package, name );
1145 if (prop)
1146 value = atoiW( prop->value );
1147 return value;
1148}
1149
a4fb1c94 1150static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name,
3e6f31bf 1151 awstring *szValueBuf, DWORD* pchValueBuf )
181705cb 1152{
3e6f31bf 1153 static const WCHAR empty[] = {0};
a4fb1c94 1154 msi_property *prop;
181705cb 1155 MSIPACKAGE *package;
3e6f31bf
MM
1156 UINT r;
1157 LPCWSTR val = NULL;
181705cb 1158
3e6f31bf
MM
1159 TRACE("%lu %s %p %p\n", handle, debugstr_w(name),
1160 szValueBuf->str.w, pchValueBuf );
181705cb 1161
3e6f31bf 1162 if (!name)
181705cb 1163 return ERROR_INVALID_PARAMETER;
639048b9 1164
3e6f31bf 1165 package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE );
181705cb
MM
1166 if (!package)
1167 return ERROR_INVALID_HANDLE;
409d3f62 1168
a4fb1c94
MM
1169 prop = msi_prop_find( package, name );
1170 if (prop)
1171 val = prop->value;
1256a0c3 1172
3e6f31bf
MM
1173 if (!val)
1174 val = empty;
1175
1176 r = msi_strcpy_to_awstring( val, szValueBuf, pchValueBuf );
1177
3e6f31bf
MM
1178 msiobj_release( &package->hdr );
1179
1180 return r;
181705cb
MM
1181}
1182
3e6f31bf
MM
1183UINT WINAPI MsiGetPropertyA( MSIHANDLE hInstall, LPCSTR szName,
1184 LPSTR szValueBuf, DWORD* pchValueBuf )
a7a6f5f3 1185{
3e6f31bf
MM
1186 awstring val;
1187 LPWSTR name;
1188 UINT r;
1256a0c3 1189
3e6f31bf
MM
1190 val.unicode = FALSE;
1191 val.str.a = szValueBuf;
181705cb 1192
3e6f31bf
MM
1193 name = strdupAtoW( szName );
1194 if (szName && !name)
1195 return ERROR_OUTOFMEMORY;
639048b9 1196
3e6f31bf
MM
1197 r = MSI_GetProperty( hInstall, name, &val, pchValueBuf );
1198 msi_free( name );
1199 return r;
1200}
a4fb1c94 1201
3e6f31bf
MM
1202UINT WINAPI MsiGetPropertyW( MSIHANDLE hInstall, LPCWSTR szName,
1203 LPWSTR szValueBuf, DWORD* pchValueBuf )
1204{
1205 awstring val;
409d3f62 1206
3e6f31bf
MM
1207 val.unicode = TRUE;
1208 val.str.w = szValueBuf;
1256a0c3 1209
3e6f31bf 1210 return MSI_GetProperty( hInstall, szName, &val, pchValueBuf );
a7a6f5f3 1211}