Commit | Line | Data |
---|---|---|
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 |
48 | WINE_DEFAULT_DEBUG_CHANNEL(msi); |
49 | ||
a4fb1c94 MM |
50 | static void msi_free_properties( MSIPACKAGE *package ); |
51 | ||
64de949c | 52 | static 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 |
64 | static 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 | 76 | static 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 | */ | |
99 | static 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 |
117 | static 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 | ||
158 | done: | |
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 | * | |
171 | http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/properties.asp | |
172 | */ | |
a7a6f5f3 | 173 | static 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 |
440 | static 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 | 472 | static 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 | ||
506 | MSIPACKAGE *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 | */ | |
549 | static 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 | 568 | LPCWSTR 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 |
600 | UINT 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 | 679 | UINT 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 |
704 | UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage) |
705 | { | |
706 | return MsiOpenPackageExW( szPackage, 0, phPackage ); | |
707 | } | |
708 | ||
eb0e0df9 AS |
709 | UINT 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 | 728 | UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage) |
eb0e0df9 | 729 | { |
279ef156 | 730 | return MsiOpenPackageExA( szPackage, 0, phPackage ); |
eb0e0df9 AS |
731 | } |
732 | ||
733 | MSIHANDLE 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 |
750 | INT 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 |
918 | INT 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 | ||
935 | out: | |
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 | |
945 | typedef struct msi_property { | |
946 | struct list entry; | |
947 | LPWSTR key; | |
948 | LPWSTR value; | |
949 | } msi_property; | |
950 | ||
951 | static 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 | ||
967 | static 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 | ||
978 | static 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 | ||
993 | static 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 | ||
1001 | static 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 | 1017 | UINT 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 | |
1032 | end: | |
8dc28d53 MM |
1033 | msi_free( szwName ); |
1034 | msi_free( szwValue ); | |
eb0e0df9 | 1035 | |
3e6f31bf | 1036 | return r; |
eb0e0df9 AS |
1037 | } |
1038 | ||
a7a6f5f3 | 1039 | UINT 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 |
1070 | UINT 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 */ |
1084 | UINT 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 |
1128 | LPWSTR 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 | ||
1140 | int 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 | 1150 | static 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 |
1183 | UINT 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 |
1202 | UINT 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 | } |