1 /*
2 * Implementation of the Microsoft Installer (msi.dll)
3 *
4 * Copyright 2002,2003,2004,2005 Mike McCormack 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
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include <stdarg.h>
22
23 #define COBJMACROS
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winreg.h"
27 #include "winnls.h"
28 #include "shlwapi.h"
29 #include "msi.h"
30 #include "msidefs.h"
31 #include "msiquery.h"
32 #include "wincrypt.h"
33 #include "winver.h"
34 #include "winuser.h"
35 #include "shlobj.h"
36 #include "shobjidl.h"
37 #include "objidl.h"
38 #include "wintrust.h"
39 #include "softpub.h"
40
41 #include "msipriv.h"
42 #include "winemsi_s.h"
43
44 #include "initguid.h"
45 #include "msxml2.h"
46
47 #include "wine/debug.h"
48 #include "wine/exception.h"
49
50 WINE_DEFAULT_DEBUG_CHANNEL(msi);
51
52 BOOL is_wow64;
53
msi_locate_product(LPCWSTR szProduct,MSIINSTALLCONTEXT * context)54 UINT msi_locate_product(LPCWSTR szProduct, MSIINSTALLCONTEXT *context)
55 {
56 HKEY hkey = NULL;
57
58 *context = MSIINSTALLCONTEXT_NONE;
59 if (!szProduct) return ERROR_UNKNOWN_PRODUCT;
60
61 if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
62 &hkey, FALSE) == ERROR_SUCCESS)
63 *context = MSIINSTALLCONTEXT_USERMANAGED;
64 else if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
65 &hkey, FALSE) == ERROR_SUCCESS)
66 *context = MSIINSTALLCONTEXT_MACHINE;
67 else if (MSIREG_OpenProductKey(szProduct, NULL,
68 MSIINSTALLCONTEXT_USERUNMANAGED,
69 &hkey, FALSE) == ERROR_SUCCESS)
70 *context = MSIINSTALLCONTEXT_USERUNMANAGED;
71
72 RegCloseKey(hkey);
73
74 if (*context == MSIINSTALLCONTEXT_NONE)
75 return ERROR_UNKNOWN_PRODUCT;
76
77 return ERROR_SUCCESS;
78 }
79
MsiOpenProductA(LPCSTR szProduct,MSIHANDLE * phProduct)80 UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct)
81 {
82 UINT r;
83 LPWSTR szwProd = NULL;
84
85 TRACE("%s %p\n",debugstr_a(szProduct), phProduct);
86
87 if( szProduct )
88 {
89 szwProd = strdupAtoW( szProduct );
90 if( !szwProd )
91 return ERROR_OUTOFMEMORY;
92 }
93
94 r = MsiOpenProductW( szwProd, phProduct );
95
96 free( szwProd );
97
98 return r;
99 }
100
MSI_OpenProductW(LPCWSTR szProduct,MSIPACKAGE ** package)101 static UINT MSI_OpenProductW(LPCWSTR szProduct, MSIPACKAGE **package)
102 {
103 UINT r;
104 HKEY props;
105 LPWSTR path;
106 MSIINSTALLCONTEXT context;
107
108 TRACE("%s %p\n", debugstr_w(szProduct), package);
109
110 r = msi_locate_product(szProduct, &context);
111 if (r != ERROR_SUCCESS)
112 return r;
113
114 r = MSIREG_OpenInstallProps(szProduct, context, NULL, &props, FALSE);
115 if (r != ERROR_SUCCESS)
116 return ERROR_UNKNOWN_PRODUCT;
117
118 if (context == MSIINSTALLCONTEXT_USERMANAGED)
119 path = msi_reg_get_val_str(props, L"ManagedLocalPackage");
120 else
121 path = msi_reg_get_val_str(props, L"LocalPackage");
122
123 r = ERROR_UNKNOWN_PRODUCT;
124
125 if (!path || GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES)
126 goto done;
127
128 if (PathIsRelativeW(path))
129 {
130 r = ERROR_INSTALL_PACKAGE_OPEN_FAILED;
131 goto done;
132 }
133
134 r = MSI_OpenPackageW(path, 0, package);
135
136 done:
137 RegCloseKey(props);
138 free(path);
139 return r;
140 }
141
MsiOpenProductW(LPCWSTR szProduct,MSIHANDLE * phProduct)142 UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct)
143 {
144 MSIPACKAGE *package = NULL;
145 WCHAR squashed_pc[SQUASHED_GUID_SIZE];
146 UINT r;
147
148 if (!szProduct || !squash_guid( szProduct, squashed_pc ))
149 return ERROR_INVALID_PARAMETER;
150
151 if (!phProduct)
152 return ERROR_INVALID_PARAMETER;
153
154 r = MSI_OpenProductW(szProduct, &package);
155 if (r != ERROR_SUCCESS)
156 return r;
157
158 *phProduct = alloc_msihandle(&package->hdr);
159 if (!*phProduct)
160 r = ERROR_NOT_ENOUGH_MEMORY;
161
162 msiobj_release(&package->hdr);
163 return r;
164 }
165
MsiAdvertiseProductA(LPCSTR szPackagePath,LPCSTR szScriptfilePath,LPCSTR szTransforms,LANGID lgidLanguage)166 UINT WINAPI MsiAdvertiseProductA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
167 LPCSTR szTransforms, LANGID lgidLanguage)
168 {
169 FIXME("%s %s %s %08x\n",debugstr_a(szPackagePath),
170 debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage);
171 return ERROR_CALL_NOT_IMPLEMENTED;
172 }
173
MsiAdvertiseProductW(LPCWSTR szPackagePath,LPCWSTR szScriptfilePath,LPCWSTR szTransforms,LANGID lgidLanguage)174 UINT WINAPI MsiAdvertiseProductW(LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
175 LPCWSTR szTransforms, LANGID lgidLanguage)
176 {
177 FIXME("%s %s %s %08x\n",debugstr_w(szPackagePath),
178 debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage);
179 return ERROR_CALL_NOT_IMPLEMENTED;
180 }
181
MsiAdvertiseProductExA(const char * szPackagePath,const char * szScriptfilePath,const char * szTransforms,LANGID lgidLanguage,DWORD dwPlatform,DWORD dwOptions)182 UINT WINAPI MsiAdvertiseProductExA( const char *szPackagePath, const char *szScriptfilePath,
183 const char *szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions )
184 {
185 FIXME( "%s, %s, %s, %#x, %#lx, %#lx\n", debugstr_a(szPackagePath), debugstr_a(szScriptfilePath),
186 debugstr_a(szTransforms), lgidLanguage, dwPlatform, dwOptions );
187 return ERROR_CALL_NOT_IMPLEMENTED;
188 }
189
MsiAdvertiseProductExW(const WCHAR * szPackagePath,const WCHAR * szScriptfilePath,const WCHAR * szTransforms,LANGID lgidLanguage,DWORD dwPlatform,DWORD dwOptions)190 UINT WINAPI MsiAdvertiseProductExW( const WCHAR *szPackagePath, const WCHAR *szScriptfilePath,
191 const WCHAR *szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions )
192 {
193 FIXME( "%s, %s, %s, %#x %#lx %#lx\n", debugstr_w(szPackagePath), debugstr_w(szScriptfilePath),
194 debugstr_w(szTransforms), lgidLanguage, dwPlatform, dwOptions );
195 return ERROR_CALL_NOT_IMPLEMENTED;
196 }
197
MsiInstallProductA(LPCSTR szPackagePath,LPCSTR szCommandLine)198 UINT WINAPI MsiInstallProductA(LPCSTR szPackagePath, LPCSTR szCommandLine)
199 {
200 LPWSTR szwPath = NULL, szwCommand = NULL;
201 UINT r = ERROR_OUTOFMEMORY;
202
203 TRACE("%s %s\n",debugstr_a(szPackagePath), debugstr_a(szCommandLine));
204
205 if( szPackagePath )
206 {
207 szwPath = strdupAtoW( szPackagePath );
208 if( !szwPath )
209 goto end;
210 }
211
212 if( szCommandLine )
213 {
214 szwCommand = strdupAtoW( szCommandLine );
215 if( !szwCommand )
216 goto end;
217 }
218
219 r = MsiInstallProductW( szwPath, szwCommand );
220
221 end:
222 free( szwPath );
223 free( szwCommand );
224
225 return r;
226 }
227
MsiInstallProductW(LPCWSTR szPackagePath,LPCWSTR szCommandLine)228 UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
229 {
230 MSIPACKAGE *package = NULL;
231 const WCHAR *reinstallmode;
232 DWORD options = 0;
233 UINT r, len;
234
235 TRACE("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine));
236
237 if (!szPackagePath)
238 return ERROR_INVALID_PARAMETER;
239
240 if (!*szPackagePath)
241 return ERROR_PATH_NOT_FOUND;
242
243 reinstallmode = msi_get_command_line_option(szCommandLine, L"REINSTALLMODE", &len);
244 if (reinstallmode)
245 {
246 while (len > 0)
247 {
248 if (reinstallmode[--len] == 'v' || reinstallmode[len] == 'V')
249 {
250 options |= WINE_OPENPACKAGEFLAGS_RECACHE;
251 break;
252 }
253 }
254 }
255
256 r = MSI_OpenPackageW( szPackagePath, options, &package );
257 if (r == ERROR_SUCCESS)
258 {
259 r = MSI_InstallPackage( package, szPackagePath, szCommandLine );
260 msiobj_release( &package->hdr );
261 }
262
263 return r;
264 }
265
MsiReinstallProductA(const char * szProduct,DWORD dwReinstallMode)266 UINT WINAPI MsiReinstallProductA( const char *szProduct, DWORD dwReinstallMode )
267 {
268 WCHAR *wszProduct;
269 UINT rc;
270
271 TRACE( "%s, %#lx\n", debugstr_a(szProduct), dwReinstallMode );
272
273 wszProduct = strdupAtoW(szProduct);
274 rc = MsiReinstallProductW(wszProduct, dwReinstallMode);
275 free(wszProduct);
276 return rc;
277 }
278
MsiReinstallProductW(const WCHAR * szProduct,DWORD dwReinstallMode)279 UINT WINAPI MsiReinstallProductW( const WCHAR *szProduct, DWORD dwReinstallMode )
280 {
281 TRACE( "%s, %#lx\n", debugstr_w(szProduct), dwReinstallMode );
282
283 return MsiReinstallFeatureW(szProduct, L"ALL", dwReinstallMode);
284 }
285
MsiApplyPatchA(LPCSTR szPatchPackage,LPCSTR szInstallPackage,INSTALLTYPE eInstallType,LPCSTR szCommandLine)286 UINT WINAPI MsiApplyPatchA(LPCSTR szPatchPackage, LPCSTR szInstallPackage,
287 INSTALLTYPE eInstallType, LPCSTR szCommandLine)
288 {
289 LPWSTR patch_package = NULL;
290 LPWSTR install_package = NULL;
291 LPWSTR command_line = NULL;
292 UINT r = ERROR_OUTOFMEMORY;
293
294 TRACE("%s %s %d %s\n", debugstr_a(szPatchPackage), debugstr_a(szInstallPackage),
295 eInstallType, debugstr_a(szCommandLine));
296
297 if (szPatchPackage && !(patch_package = strdupAtoW(szPatchPackage)))
298 goto done;
299
300 if (szInstallPackage && !(install_package = strdupAtoW(szInstallPackage)))
301 goto done;
302
303 if (szCommandLine && !(command_line = strdupAtoW(szCommandLine)))
304 goto done;
305
306 r = MsiApplyPatchW(patch_package, install_package, eInstallType, command_line);
307
308 done:
309 free(patch_package);
310 free(install_package);
311 free(command_line);
312
313 return r;
314 }
315
get_patch_product_codes(LPCWSTR szPatchPackage,WCHAR *** product_codes)316 static UINT get_patch_product_codes( LPCWSTR szPatchPackage, WCHAR ***product_codes )
317 {
318 MSIHANDLE patch, info = 0;
319 UINT r, type;
320 DWORD size;
321 static WCHAR empty[] = L"";
322 WCHAR *codes = NULL;
323
324 r = MsiOpenDatabaseW( szPatchPackage, MSIDBOPEN_READONLY, &patch );
325 if (r != ERROR_SUCCESS)
326 return r;
327
328 r = MsiGetSummaryInformationW( patch, NULL, 0, &info );
329 if (r != ERROR_SUCCESS)
330 goto done;
331
332 size = 0;
333 r = MsiSummaryInfoGetPropertyW( info, PID_TEMPLATE, &type, NULL, NULL, empty, &size );
334 if (r != ERROR_MORE_DATA || !size || type != VT_LPSTR)
335 {
336 ERR("Failed to read product codes from patch\n");
337 r = ERROR_FUNCTION_FAILED;
338 goto done;
339 }
340
341 codes = malloc( ++size * sizeof(WCHAR) );
342 if (!codes)
343 {
344 r = ERROR_OUTOFMEMORY;
345 goto done;
346 }
347
348 r = MsiSummaryInfoGetPropertyW( info, PID_TEMPLATE, &type, NULL, NULL, codes, &size );
349 if (r == ERROR_SUCCESS)
350 *product_codes = msi_split_string( codes, ';' );
351
352 done:
353 MsiCloseHandle( info );
354 MsiCloseHandle( patch );
355 free( codes );
356 return r;
357 }
358
MSI_ApplyPatchW(LPCWSTR szPatchPackage,LPCWSTR szProductCode,LPCWSTR szCommandLine)359 static UINT MSI_ApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szProductCode, LPCWSTR szCommandLine)
360 {
361 UINT i, r = ERROR_FUNCTION_FAILED;
362 DWORD size;
363 LPCWSTR cmd_ptr = szCommandLine;
364 LPWSTR cmd, *codes = NULL;
365 BOOL succeeded = FALSE;
366
367 if (!szPatchPackage || !szPatchPackage[0])
368 return ERROR_INVALID_PARAMETER;
369
370 if (!szProductCode && (r = get_patch_product_codes( szPatchPackage, &codes )))
371 return r;
372
373 if (!szCommandLine)
374 cmd_ptr = L"";
375
376 size = lstrlenW(cmd_ptr) + lstrlenW(L"%s PATCH=\"%s\"") + lstrlenW(szPatchPackage) + 1;
377 cmd = malloc(size * sizeof(WCHAR));
378 if (!cmd)
379 {
380 free(codes);
381 return ERROR_OUTOFMEMORY;
382 }
383 swprintf(cmd, size, L"%s PATCH=\"%s\"", cmd_ptr, szPatchPackage);
384
385 if (szProductCode)
386 r = MsiConfigureProductExW(szProductCode, INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd);
387 else
388 {
389 for (i = 0; codes[i]; i++)
390 {
391 r = MsiConfigureProductExW(codes[i], INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd);
392 if (r == ERROR_SUCCESS)
393 {
394 TRACE("patch applied\n");
395 succeeded = TRUE;
396 }
397 }
398
399 if (succeeded)
400 r = ERROR_SUCCESS;
401 }
402
403 free(cmd);
404 free(codes);
405 return r;
406 }
407
MsiApplyPatchW(LPCWSTR szPatchPackage,LPCWSTR szInstallPackage,INSTALLTYPE eInstallType,LPCWSTR szCommandLine)408 UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage,
409 INSTALLTYPE eInstallType, LPCWSTR szCommandLine)
410 {
411 TRACE("%s %s %d %s\n", debugstr_w(szPatchPackage), debugstr_w(szInstallPackage),
412 eInstallType, debugstr_w(szCommandLine));
413
414 if (szInstallPackage || eInstallType == INSTALLTYPE_NETWORK_IMAGE ||
415 eInstallType == INSTALLTYPE_SINGLE_INSTANCE)
416 {
417 FIXME("Only reading target products from patch\n");
418 return ERROR_CALL_NOT_IMPLEMENTED;
419 }
420
421 return MSI_ApplyPatchW(szPatchPackage, NULL, szCommandLine);
422 }
423
MsiApplyMultiplePatchesA(LPCSTR szPatchPackages,LPCSTR szProductCode,LPCSTR szPropertiesList)424 UINT WINAPI MsiApplyMultiplePatchesA(LPCSTR szPatchPackages,
425 LPCSTR szProductCode, LPCSTR szPropertiesList)
426 {
427 LPWSTR patch_packages = NULL;
428 LPWSTR product_code = NULL;
429 LPWSTR properties_list = NULL;
430 UINT r = ERROR_OUTOFMEMORY;
431
432 TRACE("%s %s %s\n", debugstr_a(szPatchPackages), debugstr_a(szProductCode),
433 debugstr_a(szPropertiesList));
434
435 if (!szPatchPackages || !szPatchPackages[0])
436 return ERROR_INVALID_PARAMETER;
437
438 if (!(patch_packages = strdupAtoW(szPatchPackages)))
439 return ERROR_OUTOFMEMORY;
440
441 if (szProductCode && !(product_code = strdupAtoW(szProductCode)))
442 goto done;
443
444 if (szPropertiesList && !(properties_list = strdupAtoW(szPropertiesList)))
445 goto done;
446
447 r = MsiApplyMultiplePatchesW(patch_packages, product_code, properties_list);
448
449 done:
450 free(patch_packages);
451 free(product_code);
452 free(properties_list);
453
454 return r;
455 }
456
MsiApplyMultiplePatchesW(LPCWSTR szPatchPackages,LPCWSTR szProductCode,LPCWSTR szPropertiesList)457 UINT WINAPI MsiApplyMultiplePatchesW(LPCWSTR szPatchPackages,
458 LPCWSTR szProductCode, LPCWSTR szPropertiesList)
459 {
460 UINT r = ERROR_SUCCESS;
461 LPCWSTR beg, end;
462
463 TRACE("%s %s %s\n", debugstr_w(szPatchPackages), debugstr_w(szProductCode),
464 debugstr_w(szPropertiesList));
465
466 if (!szPatchPackages || !szPatchPackages[0])
467 return ERROR_INVALID_PARAMETER;
468
469 beg = end = szPatchPackages;
470 while (*beg)
471 {
472 DWORD len;
473 LPWSTR patch;
474
475 while (*beg == ' ') beg++;
476 while (*end && *end != ';') end++;
477
478 len = end - beg;
479 while (len && beg[len - 1] == ' ') len--;
480
481 if (!len) return ERROR_INVALID_NAME;
482
483 patch = malloc((len + 1) * sizeof(WCHAR));
484 if (!patch)
485 return ERROR_OUTOFMEMORY;
486
487 memcpy(patch, beg, len * sizeof(WCHAR));
488 patch[len] = '\0';
489
490 r = MSI_ApplyPatchW(patch, szProductCode, szPropertiesList);
491 free(patch);
492
493 if (r != ERROR_SUCCESS || !*end)
494 break;
495
496 beg = ++end;
497 }
498 return r;
499 }
500
free_patchinfo(DWORD count,MSIPATCHSEQUENCEINFOW * info)501 static void free_patchinfo( DWORD count, MSIPATCHSEQUENCEINFOW *info )
502 {
503 DWORD i;
504 for (i = 0; i < count; i++) free( (WCHAR *)info[i].szPatchData );
505 free( info );
506 }
507
patchinfoAtoW(DWORD count,const MSIPATCHSEQUENCEINFOA * info)508 static MSIPATCHSEQUENCEINFOW *patchinfoAtoW( DWORD count, const MSIPATCHSEQUENCEINFOA *info )
509 {
510 DWORD i;
511 MSIPATCHSEQUENCEINFOW *ret;
512
513 if (!(ret = malloc( count * sizeof(MSIPATCHSEQUENCEINFOW) ))) return NULL;
514 for (i = 0; i < count; i++)
515 {
516 if (info[i].szPatchData && !(ret[i].szPatchData = strdupAtoW( info[i].szPatchData )))
517 {
518 free_patchinfo( i, ret );
519 return NULL;
520 }
521 ret[i].ePatchDataType = info[i].ePatchDataType;
522 ret[i].dwOrder = info[i].dwOrder;
523 ret[i].uStatus = info[i].uStatus;
524 }
525 return ret;
526 }
527
MsiDetermineApplicablePatchesA(const char * szProductPackagePath,DWORD cPatchInfo,MSIPATCHSEQUENCEINFOA * pPatchInfo)528 UINT WINAPI MsiDetermineApplicablePatchesA( const char *szProductPackagePath, DWORD cPatchInfo,
529 MSIPATCHSEQUENCEINFOA *pPatchInfo )
530 {
531 UINT i, r;
532 WCHAR *package_path = NULL;
533 MSIPATCHSEQUENCEINFOW *psi;
534
535 TRACE( "%s, %lu, %p\n", debugstr_a(szProductPackagePath), cPatchInfo, pPatchInfo );
536
537 if (szProductPackagePath && !(package_path = strdupAtoW( szProductPackagePath )))
538 return ERROR_OUTOFMEMORY;
539
540 if (!(psi = patchinfoAtoW( cPatchInfo, pPatchInfo )))
541 {
542 free( package_path );
543 return ERROR_OUTOFMEMORY;
544 }
545 r = MsiDetermineApplicablePatchesW( package_path, cPatchInfo, psi );
546 if (r == ERROR_SUCCESS)
547 {
548 for (i = 0; i < cPatchInfo; i++)
549 {
550 pPatchInfo[i].dwOrder = psi[i].dwOrder;
551 pPatchInfo[i].uStatus = psi[i].uStatus;
552 }
553 }
554 free( package_path );
555 free_patchinfo( cPatchInfo, psi );
556 return r;
557 }
558
MSI_ApplicablePatchW(MSIPACKAGE * package,LPCWSTR patch)559 static UINT MSI_ApplicablePatchW( MSIPACKAGE *package, LPCWSTR patch )
560 {
561 MSISUMMARYINFO *si;
562 MSIDATABASE *patch_db;
563 UINT r;
564
565 r = MSI_OpenDatabaseW( patch, MSIDBOPEN_READONLY, &patch_db );
566 if (r != ERROR_SUCCESS)
567 {
568 WARN("failed to open patch file %s\n", debugstr_w(patch));
569 return r;
570 }
571
572 r = msi_get_suminfo( patch_db->storage, 0, &si );
573 if (r != ERROR_SUCCESS)
574 {
575 msiobj_release( &patch_db->hdr );
576 return ERROR_FUNCTION_FAILED;
577 }
578
579 r = msi_check_patch_applicable( package, si );
580 if (r != ERROR_SUCCESS)
581 TRACE("patch not applicable\n");
582
583 msiobj_release( &patch_db->hdr );
584 msiobj_release( &si->hdr );
585 return r;
586 }
587
588 /* IXMLDOMDocument should be set to XPath mode already */
MSI_ApplicablePatchXML(MSIPACKAGE * package,IXMLDOMDocument * desc)589 static UINT MSI_ApplicablePatchXML( MSIPACKAGE *package, IXMLDOMDocument *desc )
590 {
591 UINT r = ERROR_FUNCTION_FAILED;
592 IXMLDOMNodeList *list;
593 LPWSTR product_code;
594 IXMLDOMNode *node;
595 HRESULT hr;
596 BSTR s;
597
598 product_code = msi_dup_property( package->db, L"ProductCode" );
599 if (!product_code)
600 {
601 /* FIXME: the property ProductCode should be written into the DB somewhere */
602 ERR("no product code to check\n");
603 return ERROR_SUCCESS;
604 }
605
606 s = SysAllocString( L"MsiPatch/TargetProduct/TargetProductCode" );
607 hr = IXMLDOMDocument_selectNodes( desc, s, &list );
608 SysFreeString(s);
609 if (hr != S_OK)
610 return ERROR_INVALID_PATCH_XML;
611
612 while (IXMLDOMNodeList_nextNode( list, &node ) == S_OK && r != ERROR_SUCCESS)
613 {
614 hr = IXMLDOMNode_get_text( node, &s );
615 IXMLDOMNode_Release( node );
616 if (hr == S_OK)
617 {
618 if (!wcscmp( s, product_code )) r = ERROR_SUCCESS;
619 SysFreeString( s );
620 }
621 }
622 IXMLDOMNodeList_Release( list );
623
624 if (r != ERROR_SUCCESS)
625 TRACE("patch not applicable\n");
626
627 free( product_code );
628 return r;
629 }
630
determine_patch_sequence(MSIPACKAGE * package,DWORD count,MSIPATCHSEQUENCEINFOW * info)631 static UINT determine_patch_sequence( MSIPACKAGE *package, DWORD count, MSIPATCHSEQUENCEINFOW *info )
632 {
633 IXMLDOMDocument *desc = NULL;
634 DWORD i;
635
636 if (count > 1)
637 FIXME("patch ordering not supported\n");
638
639 for (i = 0; i < count; i++)
640 {
641 switch (info[i].ePatchDataType)
642 {
643 case MSIPATCH_DATATYPE_PATCHFILE:
644 {
645 if (MSI_ApplicablePatchW( package, info[i].szPatchData ) != ERROR_SUCCESS)
646 {
647 info[i].dwOrder = ~0u;
648 info[i].uStatus = ERROR_PATCH_TARGET_NOT_FOUND;
649 }
650 else
651 {
652 info[i].dwOrder = i;
653 info[i].uStatus = ERROR_SUCCESS;
654 }
655 break;
656 }
657 case MSIPATCH_DATATYPE_XMLPATH:
658 case MSIPATCH_DATATYPE_XMLBLOB:
659 {
660 VARIANT_BOOL b;
661 HRESULT hr;
662 BSTR s;
663
664 if (!desc)
665 {
666 hr = CoCreateInstance( &CLSID_DOMDocument30, NULL, CLSCTX_INPROC_SERVER,
667 &IID_IXMLDOMDocument, (void**)&desc );
668 if (hr != S_OK)
669 {
670 ERR( "failed to create DOMDocument30 instance, %#lx\n", hr );
671 return ERROR_FUNCTION_FAILED;
672 }
673 }
674
675 s = SysAllocString( info[i].szPatchData );
676 if (info[i].ePatchDataType == MSIPATCH_DATATYPE_XMLPATH)
677 {
678 VARIANT src;
679
680 V_VT(&src) = VT_BSTR;
681 V_BSTR(&src) = s;
682 hr = IXMLDOMDocument_load( desc, src, &b );
683 }
684 else
685 hr = IXMLDOMDocument_loadXML( desc, s, &b );
686 SysFreeString( s );
687 if ( hr != S_OK )
688 {
689 ERR("failed to parse patch description\n");
690 IXMLDOMDocument_Release( desc );
691 break;
692 }
693
694 if (MSI_ApplicablePatchXML( package, desc ) != ERROR_SUCCESS)
695 {
696 info[i].dwOrder = ~0u;
697 info[i].uStatus = ERROR_PATCH_TARGET_NOT_FOUND;
698 }
699 else
700 {
701 info[i].dwOrder = i;
702 info[i].uStatus = ERROR_SUCCESS;
703 }
704 break;
705 }
706 default:
707 {
708 FIXME("unknown patch data type %u\n", info[i].ePatchDataType);
709 info[i].dwOrder = i;
710 info[i].uStatus = ERROR_SUCCESS;
711 break;
712 }
713 }
714
715 TRACE("szPatchData: %s\n", debugstr_w(info[i].szPatchData));
716 TRACE("ePatchDataType: %u\n", info[i].ePatchDataType);
717 TRACE("dwOrder: %lu\n", info[i].dwOrder);
718 TRACE("uStatus: %u\n", info[i].uStatus);
719 }
720
721 if (desc) IXMLDOMDocument_Release( desc );
722
723 return ERROR_SUCCESS;
724 }
725
MsiDetermineApplicablePatchesW(const WCHAR * szProductPackagePath,DWORD cPatchInfo,MSIPATCHSEQUENCEINFOW * pPatchInfo)726 UINT WINAPI MsiDetermineApplicablePatchesW( const WCHAR *szProductPackagePath, DWORD cPatchInfo,
727 MSIPATCHSEQUENCEINFOW *pPatchInfo )
728 {
729 UINT r;
730 MSIPACKAGE *package;
731
732 TRACE( "%s, %lu, %p\n", debugstr_w(szProductPackagePath), cPatchInfo, pPatchInfo );
733
734 r = MSI_OpenPackageW( szProductPackagePath, 0, &package );
735 if (r != ERROR_SUCCESS)
736 {
737 ERR("failed to open package %u\n", r);
738 return r;
739 }
740 r = determine_patch_sequence( package, cPatchInfo, pPatchInfo );
741 msiobj_release( &package->hdr );
742 return r;
743 }
744
MsiDeterminePatchSequenceA(const char * product,const char * usersid,MSIINSTALLCONTEXT context,DWORD count,MSIPATCHSEQUENCEINFOA * patchinfo)745 UINT WINAPI MsiDeterminePatchSequenceA( const char *product, const char *usersid, MSIINSTALLCONTEXT context,
746 DWORD count, MSIPATCHSEQUENCEINFOA *patchinfo )
747 {
748 UINT i, r;
749 WCHAR *productW, *usersidW = NULL;
750 MSIPATCHSEQUENCEINFOW *patchinfoW;
751
752 TRACE( "%s, %s, %d, %lu, %p\n", debugstr_a(product), debugstr_a(usersid), context, count, patchinfo );
753
754 if (!product) return ERROR_INVALID_PARAMETER;
755 if (!(productW = strdupAtoW( product ))) return ERROR_OUTOFMEMORY;
756 if (usersid && !(usersidW = strdupAtoW( usersid )))
757 {
758 free( productW );
759 return ERROR_OUTOFMEMORY;
760 }
761 if (!(patchinfoW = patchinfoAtoW( count, patchinfo )))
762 {
763 free( productW );
764 free( usersidW );
765 return ERROR_OUTOFMEMORY;
766 }
767 r = MsiDeterminePatchSequenceW( productW, usersidW, context, count, patchinfoW );
768 if (r == ERROR_SUCCESS)
769 {
770 for (i = 0; i < count; i++)
771 {
772 patchinfo[i].dwOrder = patchinfoW[i].dwOrder;
773 patchinfo[i].uStatus = patchinfoW[i].uStatus;
774 }
775 }
776 free( productW );
777 free( usersidW );
778 free_patchinfo( count, patchinfoW );
779 return r;
780 }
781
open_package(const WCHAR * product,const WCHAR * usersid,MSIINSTALLCONTEXT context,MSIPACKAGE ** package)782 static UINT open_package( const WCHAR *product, const WCHAR *usersid,
783 MSIINSTALLCONTEXT context, MSIPACKAGE **package )
784 {
785 UINT r;
786 HKEY props;
787 WCHAR *localpath, sourcepath[MAX_PATH], filename[MAX_PATH];
788
789 r = MSIREG_OpenInstallProps( product, context, usersid, &props, FALSE );
790 if (r != ERROR_SUCCESS) return ERROR_BAD_CONFIGURATION;
791
792 if ((localpath = msi_reg_get_val_str( props, L"LocalPackage" )))
793 {
794 lstrcpyW( sourcepath, localpath );
795 free( localpath );
796 }
797 RegCloseKey( props );
798 if (!localpath || GetFileAttributesW( sourcepath ) == INVALID_FILE_ATTRIBUTES)
799 {
800 DWORD sz = sizeof(sourcepath);
801 MsiSourceListGetInfoW( product, usersid, context, MSICODE_PRODUCT,
802 INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz );
803 sz = sizeof(filename);
804 MsiSourceListGetInfoW( product, usersid, context, MSICODE_PRODUCT,
805 INSTALLPROPERTY_PACKAGENAMEW, filename, &sz );
806 lstrcatW( sourcepath, filename );
807 }
808 if (GetFileAttributesW( sourcepath ) == INVALID_FILE_ATTRIBUTES)
809 return ERROR_INSTALL_SOURCE_ABSENT;
810
811 return MSI_OpenPackageW( sourcepath, 0, package );
812 }
813
MsiDeterminePatchSequenceW(const WCHAR * product,const WCHAR * usersid,MSIINSTALLCONTEXT context,DWORD count,MSIPATCHSEQUENCEINFOW * patchinfo)814 UINT WINAPI MsiDeterminePatchSequenceW( const WCHAR *product, const WCHAR *usersid, MSIINSTALLCONTEXT context,
815 DWORD count, MSIPATCHSEQUENCEINFOW *patchinfo )
816 {
817 UINT r;
818 MSIPACKAGE *package;
819
820 TRACE( "%s, %s, %d, %lu, %p\n", debugstr_w(product), debugstr_w(usersid), context, count, patchinfo );
821
822 if (!product) return ERROR_INVALID_PARAMETER;
823 r = open_package( product, usersid, context, &package );
824 if (r != ERROR_SUCCESS) return r;
825
826 r = determine_patch_sequence( package, count, patchinfo );
827 msiobj_release( &package->hdr );
828 return r;
829 }
830
MsiConfigureProductExW(LPCWSTR szProduct,int iInstallLevel,INSTALLSTATE eInstallState,LPCWSTR szCommandLine)831 UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
832 INSTALLSTATE eInstallState, LPCWSTR szCommandLine)
833 {
834 MSIPACKAGE* package = NULL;
835 MSIINSTALLCONTEXT context;
836 UINT r;
837 DWORD sz;
838 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH];
839 LPWSTR commandline;
840
841 TRACE("%s %d %d %s\n",debugstr_w(szProduct), iInstallLevel, eInstallState,
842 debugstr_w(szCommandLine));
843
844 if (!szProduct || lstrlenW(szProduct) != GUID_SIZE - 1)
845 return ERROR_INVALID_PARAMETER;
846
847 if (eInstallState == INSTALLSTATE_ADVERTISED ||
848 eInstallState == INSTALLSTATE_SOURCE)
849 {
850 FIXME("State %d not implemented\n", eInstallState);
851 return ERROR_CALL_NOT_IMPLEMENTED;
852 }
853
854 r = msi_locate_product(szProduct, &context);
855 if (r != ERROR_SUCCESS)
856 return r;
857
858 r = open_package(szProduct, NULL, context, &package);
859 if (r != ERROR_SUCCESS)
860 return r;
861
862 sz = lstrlenW(L" Installed=1") + 1;
863
864 if (szCommandLine)
865 sz += lstrlenW(szCommandLine);
866
867 if (eInstallState != INSTALLSTATE_DEFAULT)
868 sz += lstrlenW(L" INSTALLLEVEL=32767");
869
870 if (eInstallState == INSTALLSTATE_ABSENT)
871 sz += lstrlenW(L" REMOVE=ALL");
872
873 if (context == MSIINSTALLCONTEXT_MACHINE)
874 sz += lstrlenW(L" ALLUSERS=1");
875
876 commandline = malloc(sz * sizeof(WCHAR));
877 if (!commandline)
878 {
879 r = ERROR_OUTOFMEMORY;
880 goto end;
881 }
882
883 commandline[0] = 0;
884 if (szCommandLine)
885 lstrcpyW(commandline, szCommandLine);
886
887 if (eInstallState != INSTALLSTATE_DEFAULT)
888 lstrcatW(commandline, L" INSTALLLEVEL=32767");
889
890 if (eInstallState == INSTALLSTATE_ABSENT)
891 lstrcatW(commandline, L" REMOVE=ALL");
892
893 if (context == MSIINSTALLCONTEXT_MACHINE)
894 lstrcatW(commandline, L" ALLUSERS=1");
895
896 sz = sizeof(sourcepath);
897 MsiSourceListGetInfoW(szProduct, NULL, context, MSICODE_PRODUCT,
898 INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
899
900 sz = sizeof(filename);
901 MsiSourceListGetInfoW(szProduct, NULL, context, MSICODE_PRODUCT,
902 INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
903
904 lstrcatW(sourcepath, filename);
905
906 r = MSI_InstallPackage( package, sourcepath, commandline );
907
908 free(commandline);
909
910 end:
911 msiobj_release( &package->hdr );
912
913 return r;
914 }
915
MsiConfigureProductExA(LPCSTR szProduct,int iInstallLevel,INSTALLSTATE eInstallState,LPCSTR szCommandLine)916 UINT WINAPI MsiConfigureProductExA(LPCSTR szProduct, int iInstallLevel,
917 INSTALLSTATE eInstallState, LPCSTR szCommandLine)
918 {
919 LPWSTR szwProduct = NULL;
920 LPWSTR szwCommandLine = NULL;
921 UINT r = ERROR_OUTOFMEMORY;
922
923 if( szProduct )
924 {
925 szwProduct = strdupAtoW( szProduct );
926 if( !szwProduct )
927 goto end;
928 }
929
930 if( szCommandLine)
931 {
932 szwCommandLine = strdupAtoW( szCommandLine );
933 if( !szwCommandLine)
934 goto end;
935 }
936
937 r = MsiConfigureProductExW( szwProduct, iInstallLevel, eInstallState,
938 szwCommandLine );
939 end:
940 free( szwProduct );
941 free( szwCommandLine);
942
943 return r;
944 }
945
MsiConfigureProductA(LPCSTR szProduct,int iInstallLevel,INSTALLSTATE eInstallState)946 UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel,
947 INSTALLSTATE eInstallState)
948 {
949 LPWSTR szwProduct = NULL;
950 UINT r;
951
952 TRACE("%s %d %d\n",debugstr_a(szProduct), iInstallLevel, eInstallState);
953
954 if( szProduct )
955 {
956 szwProduct = strdupAtoW( szProduct );
957 if( !szwProduct )
958 return ERROR_OUTOFMEMORY;
959 }
960
961 r = MsiConfigureProductW( szwProduct, iInstallLevel, eInstallState );
962 free( szwProduct );
963
964 return r;
965 }
966
MsiConfigureProductW(LPCWSTR szProduct,int iInstallLevel,INSTALLSTATE eInstallState)967 UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel,
968 INSTALLSTATE eInstallState)
969 {
970 return MsiConfigureProductExW(szProduct, iInstallLevel, eInstallState, NULL);
971 }
972
MsiGetProductCodeA(LPCSTR szComponent,LPSTR szBuffer)973 UINT WINAPI MsiGetProductCodeA(LPCSTR szComponent, LPSTR szBuffer)
974 {
975 LPWSTR szwComponent = NULL;
976 UINT r;
977 WCHAR szwBuffer[GUID_SIZE];
978
979 TRACE("%s %p\n", debugstr_a(szComponent), szBuffer);
980
981 if( szComponent )
982 {
983 szwComponent = strdupAtoW( szComponent );
984 if( !szwComponent )
985 return ERROR_OUTOFMEMORY;
986 }
987
988 *szwBuffer = '\0';
989 r = MsiGetProductCodeW( szwComponent, szwBuffer );
990
991 if(*szwBuffer)
992 WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, GUID_SIZE, NULL, NULL);
993
994 free( szwComponent );
995
996 return r;
997 }
998
MsiGetProductCodeW(LPCWSTR szComponent,LPWSTR szBuffer)999 UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer)
1000 {
1001 UINT rc, index;
1002 HKEY compkey, prodkey;
1003 WCHAR squashed_comp[SQUASHED_GUID_SIZE], squashed_prod[SQUASHED_GUID_SIZE];
1004 DWORD sz = ARRAY_SIZE(squashed_prod);
1005
1006 TRACE("%s %p\n", debugstr_w(szComponent), szBuffer);
1007
1008 if (!szComponent || !*szComponent)
1009 return ERROR_INVALID_PARAMETER;
1010
1011 if (!squash_guid( szComponent, squashed_comp ))
1012 return ERROR_INVALID_PARAMETER;
1013
1014 if (MSIREG_OpenUserDataComponentKey(szComponent, NULL, &compkey, FALSE) != ERROR_SUCCESS &&
1015 MSIREG_OpenUserDataComponentKey(szComponent, L"S-1-5-18", &compkey, FALSE) != ERROR_SUCCESS)
1016 {
1017 return ERROR_UNKNOWN_COMPONENT;
1018 }
1019
1020 rc = RegEnumValueW( compkey, 0, squashed_prod, &sz, NULL, NULL, NULL, NULL );
1021 if (rc != ERROR_SUCCESS)
1022 {
1023 RegCloseKey(compkey);
1024 return ERROR_UNKNOWN_COMPONENT;
1025 }
1026
1027 /* check simple case, only one product */
1028 rc = RegEnumValueW( compkey, 1, squashed_prod, &sz, NULL, NULL, NULL, NULL );
1029 if (rc == ERROR_NO_MORE_ITEMS)
1030 {
1031 rc = ERROR_SUCCESS;
1032 goto done;
1033 }
1034
1035 index = 0;
1036 while ((rc = RegEnumValueW( compkey, index, squashed_prod, &sz, NULL, NULL, NULL, NULL )) !=
1037 ERROR_NO_MORE_ITEMS)
1038 {
1039 index++;
1040 sz = GUID_SIZE;
1041 unsquash_guid( squashed_prod, szBuffer );
1042
1043 if (MSIREG_OpenProductKey(szBuffer, NULL,
1044 MSIINSTALLCONTEXT_USERMANAGED,
1045 &prodkey, FALSE) == ERROR_SUCCESS ||
1046 MSIREG_OpenProductKey(szBuffer, NULL,
1047 MSIINSTALLCONTEXT_USERUNMANAGED,
1048 &prodkey, FALSE) == ERROR_SUCCESS ||
1049 MSIREG_OpenProductKey(szBuffer, NULL,
1050 MSIINSTALLCONTEXT_MACHINE,
1051 &prodkey, FALSE) == ERROR_SUCCESS)
1052 {
1053 RegCloseKey(prodkey);
1054 rc = ERROR_SUCCESS;
1055 goto done;
1056 }
1057 }
1058
1059 rc = ERROR_INSTALL_FAILURE;
1060
1061 done:
1062 RegCloseKey(compkey);
1063 unsquash_guid( squashed_prod, szBuffer );
1064 return rc;
1065 }
1066
reg_get_value(HKEY hkey,const WCHAR * name,DWORD * type)1067 static WCHAR *reg_get_value( HKEY hkey, const WCHAR *name, DWORD *type )
1068 {
1069 LONG res;
1070
1071 if ((res = RegQueryValueExW( hkey, name, NULL, type, NULL, NULL )) != ERROR_SUCCESS) return NULL;
1072
1073 if (*type == REG_SZ) return msi_reg_get_val_str( hkey, name );
1074 if (*type == REG_DWORD)
1075 {
1076 WCHAR temp[11];
1077 DWORD val;
1078
1079 if (!msi_reg_get_val_dword( hkey, name, &val )) return NULL;
1080 swprintf( temp, ARRAY_SIZE(temp), L"%u", val );
1081 return wcsdup( temp );
1082 }
1083
1084 ERR( "unhandled value type %lu\n", *type );
1085 return NULL;
1086 }
1087
MSI_GetProductInfo(LPCWSTR szProduct,LPCWSTR szAttribute,awstring * szValue,LPDWORD pcchValueBuf)1088 static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
1089 awstring *szValue, LPDWORD pcchValueBuf)
1090 {
1091 static WCHAR empty[] = L"";
1092 MSIINSTALLCONTEXT context = MSIINSTALLCONTEXT_USERUNMANAGED;
1093 UINT r = ERROR_UNKNOWN_PROPERTY;
1094 HKEY prodkey, userdata, source;
1095 WCHAR *val = NULL, squashed_pc[SQUASHED_GUID_SIZE], packagecode[GUID_SIZE];
1096 BOOL badconfig = FALSE;
1097 LONG res;
1098 DWORD type = REG_NONE;
1099
1100 TRACE("%s %s %p %p\n", debugstr_w(szProduct),
1101 debugstr_w(szAttribute), szValue, pcchValueBuf);
1102
1103 if ((szValue->str.w && !pcchValueBuf) || !szProduct || !szAttribute)
1104 return ERROR_INVALID_PARAMETER;
1105
1106 if (!squash_guid( szProduct, squashed_pc ))
1107 return ERROR_INVALID_PARAMETER;
1108
1109 if ((r = MSIREG_OpenProductKey(szProduct, NULL,
1110 MSIINSTALLCONTEXT_USERMANAGED,
1111 &prodkey, FALSE)) != ERROR_SUCCESS &&
1112 (r = MSIREG_OpenProductKey(szProduct, NULL,
1113 MSIINSTALLCONTEXT_USERUNMANAGED,
1114 &prodkey, FALSE)) != ERROR_SUCCESS &&
1115 (r = MSIREG_OpenProductKey(szProduct, NULL,
1116 MSIINSTALLCONTEXT_MACHINE,
1117 &prodkey, FALSE)) == ERROR_SUCCESS)
1118 {
1119 context = MSIINSTALLCONTEXT_MACHINE;
1120 }
1121
1122 if (!wcscmp( szAttribute, INSTALLPROPERTY_HELPLINKW ) ||
1123 !wcscmp( szAttribute, INSTALLPROPERTY_HELPTELEPHONEW ) ||
1124 !wcscmp( szAttribute, INSTALLPROPERTY_INSTALLDATEW ) ||
1125 !wcscmp( szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ) ||
1126 !wcscmp( szAttribute, INSTALLPROPERTY_INSTALLLOCATIONW ) ||
1127 !wcscmp( szAttribute, INSTALLPROPERTY_INSTALLSOURCEW ) ||
1128 !wcscmp( szAttribute, INSTALLPROPERTY_LOCALPACKAGEW ) ||
1129 !wcscmp( szAttribute, INSTALLPROPERTY_PUBLISHERW ) ||
1130 !wcscmp( szAttribute, INSTALLPROPERTY_URLINFOABOUTW ) ||
1131 !wcscmp( szAttribute, INSTALLPROPERTY_URLUPDATEINFOW ) ||
1132 !wcscmp( szAttribute, INSTALLPROPERTY_VERSIONMINORW ) ||
1133 !wcscmp( szAttribute, INSTALLPROPERTY_VERSIONMAJORW ) ||
1134 !wcscmp( szAttribute, INSTALLPROPERTY_VERSIONSTRINGW ) ||
1135 !wcscmp( szAttribute, INSTALLPROPERTY_PRODUCTIDW ) ||
1136 !wcscmp( szAttribute, INSTALLPROPERTY_REGCOMPANYW ) ||
1137 !wcscmp( szAttribute, INSTALLPROPERTY_REGOWNERW ))
1138 {
1139 if (!prodkey)
1140 {
1141 r = ERROR_UNKNOWN_PRODUCT;
1142 goto done;
1143 }
1144 if (MSIREG_OpenInstallProps(szProduct, context, NULL, &userdata, FALSE))
1145 {
1146 r = ERROR_UNKNOWN_PROPERTY;
1147 goto done;
1148 }
1149
1150 if (!wcscmp( szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ))
1151 szAttribute = L"DisplayName";
1152 else if (!wcscmp( szAttribute, INSTALLPROPERTY_VERSIONSTRINGW ))
1153 szAttribute = L"DisplayVersion";
1154
1155 val = reg_get_value(userdata, szAttribute, &type);
1156 if (!val)
1157 val = empty;
1158 RegCloseKey(userdata);
1159 }
1160 else if (!wcscmp( szAttribute, INSTALLPROPERTY_INSTANCETYPEW ) ||
1161 !wcscmp( szAttribute, INSTALLPROPERTY_TRANSFORMSW ) ||
1162 !wcscmp( szAttribute, INSTALLPROPERTY_LANGUAGEW ) ||
1163 !wcscmp( szAttribute, INSTALLPROPERTY_PRODUCTNAMEW ) ||
1164 !wcscmp( szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW ) ||
1165 !wcscmp( szAttribute, INSTALLPROPERTY_PACKAGECODEW ) ||
1166 !wcscmp( szAttribute, INSTALLPROPERTY_VERSIONW ) ||
1167 !wcscmp( szAttribute, INSTALLPROPERTY_PRODUCTICONW ) ||
1168 !wcscmp( szAttribute, INSTALLPROPERTY_PACKAGENAMEW ) ||
1169 !wcscmp( szAttribute, INSTALLPROPERTY_AUTHORIZED_LUA_APPW ))
1170 {
1171 if (!prodkey)
1172 {
1173 r = ERROR_UNKNOWN_PRODUCT;
1174 goto done;
1175 }
1176
1177 if (!wcscmp( szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW ))
1178 szAttribute = L"Assignment";
1179
1180 if (!wcscmp( szAttribute, INSTALLPROPERTY_PACKAGENAMEW ))
1181 {
1182 res = RegOpenKeyW(prodkey, L"SourceList", &source);
1183 if (res != ERROR_SUCCESS)
1184 {
1185 r = ERROR_UNKNOWN_PRODUCT;
1186 goto done;
1187 }
1188
1189 val = reg_get_value(source, szAttribute, &type);
1190 if (!val)
1191 val = empty;
1192
1193 RegCloseKey(source);
1194 }
1195 else
1196 {
1197 val = reg_get_value(prodkey, szAttribute, &type);
1198 if (!val)
1199 val = empty;
1200 }
1201
1202 if (val != empty && type != REG_DWORD &&
1203 !wcscmp( szAttribute, INSTALLPROPERTY_PACKAGECODEW ))
1204 {
1205 if (lstrlenW( val ) != SQUASHED_GUID_SIZE - 1)
1206 badconfig = TRUE;
1207 else
1208 {
1209 unsquash_guid(val, packagecode);
1210 free(val);
1211 val = wcsdup(packagecode);
1212 }
1213 }
1214 }
1215
1216 if (!val)
1217 {
1218 r = ERROR_UNKNOWN_PROPERTY;
1219 goto done;
1220 }
1221
1222 if (pcchValueBuf)
1223 {
1224 int len = lstrlenW( val );
1225
1226 /* If szBuffer (szValue->str) is NULL, there's no need to copy the value
1227 * out. Also, *pcchValueBuf may be uninitialized in this case, so we
1228 * can't rely on its value.
1229 */
1230 if (szValue->str.a || szValue->str.w)
1231 {
1232 DWORD size = *pcchValueBuf;
1233 if (len < size)
1234 r = msi_strcpy_to_awstring( val, len, szValue, &size );
1235 else
1236 r = ERROR_MORE_DATA;
1237 }
1238
1239 if (!badconfig)
1240 *pcchValueBuf = len;
1241 }
1242
1243 if (badconfig)
1244 r = ERROR_BAD_CONFIGURATION;
1245
1246 if (val != empty)
1247 free(val);
1248
1249 done:
1250 RegCloseKey(prodkey);
1251 return r;
1252 }
1253
MsiGetProductInfoA(LPCSTR szProduct,LPCSTR szAttribute,LPSTR szBuffer,LPDWORD pcchValueBuf)1254 UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute,
1255 LPSTR szBuffer, LPDWORD pcchValueBuf)
1256 {
1257 LPWSTR szwProduct, szwAttribute = NULL;
1258 UINT r = ERROR_OUTOFMEMORY;
1259 awstring buffer;
1260
1261 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szAttribute),
1262 szBuffer, pcchValueBuf);
1263
1264 szwProduct = strdupAtoW( szProduct );
1265 if( szProduct && !szwProduct )
1266 goto end;
1267
1268 szwAttribute = strdupAtoW( szAttribute );
1269 if( szAttribute && !szwAttribute )
1270 goto end;
1271
1272 buffer.unicode = FALSE;
1273 buffer.str.a = szBuffer;
1274
1275 r = MSI_GetProductInfo( szwProduct, szwAttribute,
1276 &buffer, pcchValueBuf );
1277
1278 end:
1279 free( szwProduct );
1280 free( szwAttribute );
1281
1282 return r;
1283 }
1284
MsiGetProductInfoW(LPCWSTR szProduct,LPCWSTR szAttribute,LPWSTR szBuffer,LPDWORD pcchValueBuf)1285 UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute,
1286 LPWSTR szBuffer, LPDWORD pcchValueBuf)
1287 {
1288 awstring buffer;
1289
1290 TRACE("%s %s %p %p\n", debugstr_w(szProduct), debugstr_w(szAttribute),
1291 szBuffer, pcchValueBuf);
1292
1293 buffer.unicode = TRUE;
1294 buffer.str.w = szBuffer;
1295
1296 return MSI_GetProductInfo( szProduct, szAttribute,
1297 &buffer, pcchValueBuf );
1298 }
1299
MsiGetProductInfoExA(LPCSTR szProductCode,LPCSTR szUserSid,MSIINSTALLCONTEXT dwContext,LPCSTR szProperty,LPSTR szValue,LPDWORD pcchValue)1300 UINT WINAPI MsiGetProductInfoExA(LPCSTR szProductCode, LPCSTR szUserSid,
1301 MSIINSTALLCONTEXT dwContext, LPCSTR szProperty,
1302 LPSTR szValue, LPDWORD pcchValue)
1303 {
1304 LPWSTR product = NULL;
1305 LPWSTR usersid = NULL;
1306 LPWSTR property = NULL;
1307 LPWSTR value = NULL;
1308 DWORD len = 0;
1309 UINT r;
1310
1311 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_a(szProductCode),
1312 debugstr_a(szUserSid), dwContext, debugstr_a(szProperty),
1313 szValue, pcchValue);
1314
1315 if (szValue && !pcchValue)
1316 return ERROR_INVALID_PARAMETER;
1317
1318 if (szProductCode) product = strdupAtoW(szProductCode);
1319 if (szUserSid) usersid = strdupAtoW(szUserSid);
1320 if (szProperty) property = strdupAtoW(szProperty);
1321
1322 r = MsiGetProductInfoExW(product, usersid, dwContext, property,
1323 NULL, &len);
1324 if (r != ERROR_SUCCESS)
1325 goto done;
1326
1327 value = malloc(++len * sizeof(WCHAR));
1328 if (!value)
1329 {
1330 r = ERROR_OUTOFMEMORY;
1331 goto done;
1332 }
1333
1334 r = MsiGetProductInfoExW(product, usersid, dwContext, property,
1335 value, &len);
1336 if (r != ERROR_SUCCESS)
1337 goto done;
1338
1339 if (!pcchValue)
1340 goto done;
1341
1342 len = WideCharToMultiByte(CP_ACP, 0, value, -1, NULL, 0, NULL, NULL);
1343 if (*pcchValue >= len)
1344 WideCharToMultiByte(CP_ACP, 0, value, -1, szValue, len, NULL, NULL);
1345 else if (szValue)
1346 {
1347 r = ERROR_MORE_DATA;
1348 if (*pcchValue > 0)
1349 *szValue = '\0';
1350 }
1351
1352 if (*pcchValue <= len || !szValue)
1353 len = len * sizeof(WCHAR) - 1;
1354
1355 *pcchValue = len - 1;
1356
1357 done:
1358 free(product);
1359 free(usersid);
1360 free(property);
1361 free(value);
1362
1363 return r;
1364 }
1365
copy_outval(const WCHAR * val,WCHAR * out,DWORD * size)1366 static UINT copy_outval(const WCHAR *val, WCHAR *out, DWORD *size)
1367 {
1368 UINT r = ERROR_SUCCESS;
1369
1370 if (!val)
1371 return ERROR_UNKNOWN_PROPERTY;
1372
1373 if (out)
1374 {
1375 if (lstrlenW(val) >= *size)
1376 {
1377 r = ERROR_MORE_DATA;
1378 if (*size > 0)
1379 *out = '\0';
1380 }
1381 else
1382 lstrcpyW(out, val);
1383 }
1384
1385 if (size)
1386 *size = lstrlenW(val);
1387
1388 return r;
1389 }
1390
MsiGetProductInfoExW(LPCWSTR szProductCode,LPCWSTR szUserSid,MSIINSTALLCONTEXT dwContext,LPCWSTR szProperty,LPWSTR szValue,LPDWORD pcchValue)1391 UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
1392 MSIINSTALLCONTEXT dwContext, LPCWSTR szProperty,
1393 LPWSTR szValue, LPDWORD pcchValue)
1394 {
1395 WCHAR *val = NULL, squashed_pc[SQUASHED_GUID_SIZE];
1396 LPCWSTR package = NULL;
1397 HKEY props = NULL, prod, classes = NULL, managed, hkey = NULL;
1398 DWORD type;
1399 UINT r = ERROR_UNKNOWN_PRODUCT;
1400
1401 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_w(szProductCode),
1402 debugstr_w(szUserSid), dwContext, debugstr_w(szProperty),
1403 szValue, pcchValue);
1404
1405 if (!szProductCode || !squash_guid( szProductCode, squashed_pc ))
1406 return ERROR_INVALID_PARAMETER;
1407
1408 if (szValue && !pcchValue)
1409 return ERROR_INVALID_PARAMETER;
1410
1411 if (dwContext != MSIINSTALLCONTEXT_USERUNMANAGED &&
1412 dwContext != MSIINSTALLCONTEXT_USERMANAGED &&
1413 dwContext != MSIINSTALLCONTEXT_MACHINE)
1414 return ERROR_INVALID_PARAMETER;
1415
1416 if (!szProperty || !*szProperty)
1417 return ERROR_INVALID_PARAMETER;
1418
1419 if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
1420 return ERROR_INVALID_PARAMETER;
1421
1422 /* FIXME: dwContext is provided, no need to search for it */
1423 MSIREG_OpenProductKey(szProductCode, NULL,MSIINSTALLCONTEXT_USERMANAGED,
1424 &managed, FALSE);
1425 MSIREG_OpenProductKey(szProductCode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1426 &prod, FALSE);
1427
1428 MSIREG_OpenInstallProps(szProductCode, dwContext, NULL, &props, FALSE);
1429
1430 if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
1431 {
1432 package = INSTALLPROPERTY_LOCALPACKAGEW;
1433
1434 if (!props && !prod)
1435 goto done;
1436 }
1437 else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
1438 {
1439 package = L"ManagedLocalPackage";
1440
1441 if (!props && !managed)
1442 goto done;
1443 }
1444 else if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1445 {
1446 package = INSTALLPROPERTY_LOCALPACKAGEW;
1447 MSIREG_OpenProductKey(szProductCode, NULL, dwContext, &classes, FALSE);
1448
1449 if (!props && !classes)
1450 goto done;
1451 }
1452
1453 if (!wcscmp( szProperty, INSTALLPROPERTY_HELPLINKW ) ||
1454 !wcscmp( szProperty, INSTALLPROPERTY_HELPTELEPHONEW ) ||
1455 !wcscmp( szProperty, INSTALLPROPERTY_INSTALLDATEW ) ||
1456 !wcscmp( szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ) ||
1457 !wcscmp( szProperty, INSTALLPROPERTY_INSTALLLOCATIONW ) ||
1458 !wcscmp( szProperty, INSTALLPROPERTY_INSTALLSOURCEW ) ||
1459 !wcscmp( szProperty, INSTALLPROPERTY_LOCALPACKAGEW ) ||
1460 !wcscmp( szProperty, INSTALLPROPERTY_PUBLISHERW ) ||
1461 !wcscmp( szProperty, INSTALLPROPERTY_URLINFOABOUTW ) ||
1462 !wcscmp( szProperty, INSTALLPROPERTY_URLUPDATEINFOW ) ||
1463 !wcscmp( szProperty, INSTALLPROPERTY_VERSIONMINORW ) ||
1464 !wcscmp( szProperty, INSTALLPROPERTY_VERSIONMAJORW ) ||
1465 !wcscmp( szProperty, INSTALLPROPERTY_VERSIONSTRINGW ) ||
1466 !wcscmp( szProperty, INSTALLPROPERTY_PRODUCTIDW ) ||
1467 !wcscmp( szProperty, INSTALLPROPERTY_REGCOMPANYW ) ||
1468 !wcscmp( szProperty, INSTALLPROPERTY_REGOWNERW ) ||
1469 !wcscmp( szProperty, INSTALLPROPERTY_INSTANCETYPEW ))
1470 {
1471 val = reg_get_value(props, package, &type);
1472 if (!val)
1473 {
1474 if (prod || classes)
1475 r = ERROR_UNKNOWN_PROPERTY;
1476
1477 goto done;
1478 }
1479
1480 free(val);
1481
1482 if (!wcscmp( szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ))
1483 szProperty = L"DisplayName";
1484 else if (!wcscmp( szProperty, INSTALLPROPERTY_VERSIONSTRINGW ))
1485 szProperty = L"DisplayVersion";
1486
1487 val = reg_get_value(props, szProperty, &type);
1488 if (!val)
1489 val = wcsdup(L"");
1490
1491 r = copy_outval(val, szValue, pcchValue);
1492 }
1493 else if (!wcscmp( szProperty, INSTALLPROPERTY_TRANSFORMSW ) ||
1494 !wcscmp( szProperty, INSTALLPROPERTY_LANGUAGEW ) ||
1495 !wcscmp( szProperty, INSTALLPROPERTY_PRODUCTNAMEW ) ||
1496 !wcscmp( szProperty, INSTALLPROPERTY_PACKAGECODEW ) ||
1497 !wcscmp( szProperty, INSTALLPROPERTY_VERSIONW ) ||
1498 !wcscmp( szProperty, INSTALLPROPERTY_PRODUCTICONW ) ||
1499 !wcscmp( szProperty, INSTALLPROPERTY_PACKAGENAMEW ) ||
1500 !wcscmp( szProperty, INSTALLPROPERTY_AUTHORIZED_LUA_APPW ))
1501 {
1502 if (!prod && !classes)
1503 goto done;
1504
1505 if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
1506 hkey = prod;
1507 else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
1508 hkey = managed;
1509 else if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1510 hkey = classes;
1511
1512 val = reg_get_value(hkey, szProperty, &type);
1513 if (!val)
1514 val = wcsdup(L"");
1515
1516 r = copy_outval(val, szValue, pcchValue);
1517 }
1518 else if (!wcscmp( szProperty, INSTALLPROPERTY_PRODUCTSTATEW ))
1519 {
1520 if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1521 {
1522 if (props)
1523 {
1524 val = reg_get_value(props, package, &type);
1525 if (!val)
1526 goto done;
1527
1528 free(val);
1529 val = wcsdup(L"5");
1530 }
1531 else
1532 val = wcsdup(L"1");
1533
1534 r = copy_outval(val, szValue, pcchValue);
1535 goto done;
1536 }
1537 else if (props && (val = reg_get_value(props, package, &type)))
1538 {
1539 free(val);
1540 val = wcsdup(L"5");
1541 r = copy_outval(val, szValue, pcchValue);
1542 goto done;
1543 }
1544
1545 if (prod || managed)
1546 val = wcsdup(L"1");
1547 else
1548 goto done;
1549
1550 r = copy_outval(val, szValue, pcchValue);
1551 }
1552 else if (!wcscmp( szProperty, INSTALLPROPERTY_ASSIGNMENTTYPEW ))
1553 {
1554 if (!prod && !classes)
1555 goto done;
1556
1557 /* FIXME */
1558 val = wcsdup(L"");
1559 r = copy_outval(val, szValue, pcchValue);
1560 }
1561 else
1562 r = ERROR_UNKNOWN_PROPERTY;
1563
1564 done:
1565 RegCloseKey(props);
1566 RegCloseKey(prod);
1567 RegCloseKey(managed);
1568 RegCloseKey(classes);
1569 free(val);
1570
1571 return r;
1572 }
1573
MsiGetPatchFileListA(LPCSTR szProductCode,LPCSTR szPatchList,LPDWORD pcFiles,MSIHANDLE ** pphFileRecords)1574 UINT WINAPI MsiGetPatchFileListA(LPCSTR szProductCode, LPCSTR szPatchList,
1575 LPDWORD pcFiles, MSIHANDLE **pphFileRecords)
1576 {
1577 FIXME("(%s, %s, %p, %p) stub!\n", debugstr_a(szProductCode),
1578 debugstr_a(szPatchList), pcFiles, pphFileRecords);
1579 return ERROR_FUNCTION_FAILED;
1580 }
1581
MsiGetPatchFileListW(LPCWSTR szProductCode,LPCWSTR szPatchList,LPDWORD pcFiles,MSIHANDLE ** pphFileRecords)1582 UINT WINAPI MsiGetPatchFileListW(LPCWSTR szProductCode, LPCWSTR szPatchList,
1583 LPDWORD pcFiles, MSIHANDLE **pphFileRecords)
1584 {
1585 FIXME("(%s, %s, %p, %p) stub!\n", debugstr_w(szProductCode),
1586 debugstr_w(szPatchList), pcFiles, pphFileRecords);
1587 return ERROR_FUNCTION_FAILED;
1588 }
1589
MsiGetPatchInfoExA(LPCSTR szPatchCode,LPCSTR szProductCode,LPCSTR szUserSid,MSIINSTALLCONTEXT dwContext,LPCSTR szProperty,LPSTR lpValue,DWORD * pcchValue)1590 UINT WINAPI MsiGetPatchInfoExA(LPCSTR szPatchCode, LPCSTR szProductCode,
1591 LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1592 LPCSTR szProperty, LPSTR lpValue, DWORD *pcchValue)
1593 {
1594 LPWSTR patch = NULL, product = NULL, usersid = NULL;
1595 LPWSTR property = NULL, val = NULL;
1596 DWORD len;
1597 UINT r;
1598
1599 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_a(szPatchCode),
1600 debugstr_a(szProductCode), debugstr_a(szUserSid), dwContext,
1601 debugstr_a(szProperty), lpValue, pcchValue);
1602
1603 if (lpValue && !pcchValue)
1604 return ERROR_INVALID_PARAMETER;
1605
1606 if (szPatchCode) patch = strdupAtoW(szPatchCode);
1607 if (szProductCode) product = strdupAtoW(szProductCode);
1608 if (szUserSid) usersid = strdupAtoW(szUserSid);
1609 if (szProperty) property = strdupAtoW(szProperty);
1610
1611 len = 0;
1612 r = MsiGetPatchInfoExW(patch, product, usersid, dwContext, property,
1613 NULL, &len);
1614 if (r != ERROR_SUCCESS)
1615 goto done;
1616
1617 val = malloc(++len * sizeof(WCHAR));
1618 if (!val)
1619 {
1620 r = ERROR_OUTOFMEMORY;
1621 goto done;
1622 }
1623
1624 r = MsiGetPatchInfoExW(patch, product, usersid, dwContext, property,
1625 val, &len);
1626 if (r != ERROR_SUCCESS || !pcchValue)
1627 goto done;
1628
1629 if (lpValue)
1630 WideCharToMultiByte(CP_ACP, 0, val, -1, lpValue,
1631 *pcchValue - 1, NULL, NULL);
1632
1633 len = lstrlenW(val);
1634 if ((*val && *pcchValue < len + 1) || !lpValue)
1635 {
1636 if (lpValue)
1637 {
1638 r = ERROR_MORE_DATA;
1639 lpValue[*pcchValue - 1] = '\0';
1640 }
1641
1642 *pcchValue = len * sizeof(WCHAR);
1643 }
1644 else
1645 *pcchValue = len;
1646
1647 done:
1648 free(val);
1649 free(patch);
1650 free(product);
1651 free(usersid);
1652 free(property);
1653
1654 return r;
1655 }
1656
MsiGetPatchInfoExW(LPCWSTR szPatchCode,LPCWSTR szProductCode,LPCWSTR szUserSid,MSIINSTALLCONTEXT dwContext,LPCWSTR szProperty,LPWSTR lpValue,DWORD * pcchValue)1657 UINT WINAPI MsiGetPatchInfoExW(LPCWSTR szPatchCode, LPCWSTR szProductCode,
1658 LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1659 LPCWSTR szProperty, LPWSTR lpValue, DWORD *pcchValue)
1660 {
1661 WCHAR *val = NULL, squashed_pc[SQUASHED_GUID_SIZE], squashed_patch[SQUASHED_GUID_SIZE];
1662 HKEY udprod = 0, prod = 0, props = 0;
1663 HKEY patch = 0, patches = 0;
1664 HKEY udpatch = 0, datakey = 0;
1665 HKEY prodpatches = 0;
1666 UINT r = ERROR_UNKNOWN_PRODUCT;
1667 DWORD len, type;
1668 LONG res;
1669
1670 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_w(szPatchCode),
1671 debugstr_w(szProductCode), debugstr_w(szUserSid), dwContext,
1672 debugstr_w(szProperty), lpValue, pcchValue);
1673
1674 if (!szProductCode || !squash_guid( szProductCode, squashed_pc ))
1675 return ERROR_INVALID_PARAMETER;
1676
1677 if (!szPatchCode || !squash_guid( szPatchCode, squashed_patch ))
1678 return ERROR_INVALID_PARAMETER;
1679
1680 if (!szProperty)
1681 return ERROR_INVALID_PARAMETER;
1682
1683 if (lpValue && !pcchValue)
1684 return ERROR_INVALID_PARAMETER;
1685
1686 if (dwContext != MSIINSTALLCONTEXT_USERMANAGED &&
1687 dwContext != MSIINSTALLCONTEXT_USERUNMANAGED &&
1688 dwContext != MSIINSTALLCONTEXT_MACHINE)
1689 return ERROR_INVALID_PARAMETER;
1690
1691 if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
1692 return ERROR_INVALID_PARAMETER;
1693
1694 if (szUserSid && !wcscmp( szUserSid, L"S-1-5-18" ))
1695 return ERROR_INVALID_PARAMETER;
1696
1697 if (MSIREG_OpenUserDataProductKey(szProductCode, dwContext, NULL,
1698 &udprod, FALSE) != ERROR_SUCCESS)
1699 goto done;
1700
1701 if (MSIREG_OpenInstallProps(szProductCode, dwContext, NULL,
1702 &props, FALSE) != ERROR_SUCCESS)
1703 goto done;
1704
1705 r = ERROR_UNKNOWN_PATCH;
1706
1707 res = RegOpenKeyExW(udprod, L"Patches", 0, KEY_READ, &patches);
1708 if (res != ERROR_SUCCESS)
1709 goto done;
1710
1711 res = RegOpenKeyExW( patches, squashed_patch, 0, KEY_READ, &patch );
1712 if (res != ERROR_SUCCESS)
1713 goto done;
1714
1715 if (!wcscmp( szProperty, INSTALLPROPERTY_TRANSFORMSW ))
1716 {
1717 if (MSIREG_OpenProductKey(szProductCode, NULL, dwContext,
1718 &prod, FALSE) != ERROR_SUCCESS)
1719 goto done;
1720
1721 res = RegOpenKeyExW(prod, L"Patches", 0, KEY_ALL_ACCESS, &prodpatches);
1722 if (res != ERROR_SUCCESS)
1723 goto done;
1724
1725 datakey = prodpatches;
1726 szProperty = squashed_patch;
1727 }
1728 else
1729 {
1730 if (MSIREG_OpenUserDataPatchKey(szPatchCode, dwContext,
1731 &udpatch, FALSE) != ERROR_SUCCESS)
1732 goto done;
1733
1734 if (!wcscmp( szProperty, INSTALLPROPERTY_LOCALPACKAGEW ))
1735 {
1736 if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
1737 szProperty = L"ManagedLocalPackage";
1738 datakey = udpatch;
1739 }
1740 else if (!wcscmp( szProperty, INSTALLPROPERTY_INSTALLDATEW ))
1741 {
1742 datakey = patch;
1743 szProperty = L"Installed";
1744 }
1745 else if (!wcscmp( szProperty, INSTALLPROPERTY_UNINSTALLABLEW ) ||
1746 !wcscmp( szProperty, INSTALLPROPERTY_PATCHSTATEW ) ||
1747 !wcscmp( szProperty, INSTALLPROPERTY_DISPLAYNAMEW ) ||
1748 !wcscmp( szProperty, INSTALLPROPERTY_MOREINFOURLW ))
1749 {
1750 datakey = patch;
1751 }
1752 else
1753 {
1754 r = ERROR_UNKNOWN_PROPERTY;
1755 goto done;
1756 }
1757 }
1758
1759 val = reg_get_value(datakey, szProperty, &type);
1760 if (!val)
1761 val = wcsdup(L"");
1762
1763 r = ERROR_SUCCESS;
1764
1765 if (!pcchValue)
1766 goto done;
1767
1768 if (lpValue)
1769 lstrcpynW(lpValue, val, *pcchValue);
1770
1771 len = lstrlenW(val);
1772 if ((*val && *pcchValue < len + 1) || !lpValue)
1773 {
1774 if (lpValue)
1775 r = ERROR_MORE_DATA;
1776
1777 *pcchValue = len * sizeof(WCHAR);
1778 }
1779
1780 *pcchValue = len;
1781
1782 done:
1783 free(val);
1784 RegCloseKey(prodpatches);
1785 RegCloseKey(prod);
1786 RegCloseKey(patch);
1787 RegCloseKey(patches);
1788 RegCloseKey(udpatch);
1789 RegCloseKey(props);
1790 RegCloseKey(udprod);
1791
1792 return r;
1793 }
1794
MsiGetPatchInfoA(LPCSTR patch,LPCSTR attr,LPSTR buffer,LPDWORD buflen)1795 UINT WINAPI MsiGetPatchInfoA( LPCSTR patch, LPCSTR attr, LPSTR buffer, LPDWORD buflen )
1796 {
1797 UINT r = ERROR_OUTOFMEMORY;
1798 DWORD size;
1799 LPWSTR patchW = NULL, attrW = NULL, bufferW = NULL;
1800
1801 TRACE("%s %s %p %p\n", debugstr_a(patch), debugstr_a(attr), buffer, buflen);
1802
1803 if (!patch || !attr)
1804 return ERROR_INVALID_PARAMETER;
1805
1806 if (!(patchW = strdupAtoW( patch )))
1807 goto done;
1808
1809 if (!(attrW = strdupAtoW( attr )))
1810 goto done;
1811
1812 size = 0;
1813 r = MsiGetPatchInfoW( patchW, attrW, NULL, &size );
1814 if (r != ERROR_SUCCESS)
1815 goto done;
1816
1817 size++;
1818 if (!(bufferW = malloc( size * sizeof(WCHAR) )))
1819 {
1820 r = ERROR_OUTOFMEMORY;
1821 goto done;
1822 }
1823
1824 r = MsiGetPatchInfoW( patchW, attrW, bufferW, &size );
1825 if (r == ERROR_SUCCESS)
1826 {
1827 int len = WideCharToMultiByte( CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL );
1828 if (len > *buflen)
1829 r = ERROR_MORE_DATA;
1830 else if (buffer)
1831 WideCharToMultiByte( CP_ACP, 0, bufferW, -1, buffer, *buflen, NULL, NULL );
1832
1833 *buflen = len - 1;
1834 }
1835
1836 done:
1837 free( patchW );
1838 free( attrW );
1839 free( bufferW );
1840 return r;
1841 }
1842
MsiGetPatchInfoW(LPCWSTR patch,LPCWSTR attr,LPWSTR buffer,LPDWORD buflen)1843 UINT WINAPI MsiGetPatchInfoW( LPCWSTR patch, LPCWSTR attr, LPWSTR buffer, LPDWORD buflen )
1844 {
1845 UINT r;
1846 WCHAR product[GUID_SIZE];
1847 DWORD index;
1848
1849 TRACE("%s %s %p %p\n", debugstr_w(patch), debugstr_w(attr), buffer, buflen);
1850
1851 if (!patch || !attr)
1852 return ERROR_INVALID_PARAMETER;
1853
1854 if (wcscmp( INSTALLPROPERTY_LOCALPACKAGEW, attr ))
1855 return ERROR_UNKNOWN_PROPERTY;
1856
1857 index = 0;
1858 while (1)
1859 {
1860 r = MsiEnumProductsW( index, product );
1861 if (r != ERROR_SUCCESS)
1862 break;
1863
1864 r = MsiGetPatchInfoExW( patch, product, NULL, MSIINSTALLCONTEXT_USERMANAGED, attr, buffer, buflen );
1865 if (r == ERROR_SUCCESS || r == ERROR_MORE_DATA)
1866 return r;
1867
1868 r = MsiGetPatchInfoExW( patch, product, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, attr, buffer, buflen );
1869 if (r == ERROR_SUCCESS || r == ERROR_MORE_DATA)
1870 return r;
1871
1872 r = MsiGetPatchInfoExW( patch, product, NULL, MSIINSTALLCONTEXT_MACHINE, attr, buffer, buflen );
1873 if (r == ERROR_SUCCESS || r == ERROR_MORE_DATA)
1874 return r;
1875
1876 index++;
1877 }
1878
1879 return ERROR_UNKNOWN_PRODUCT;
1880 }
1881
MsiEnableLogA(DWORD dwLogMode,const char * szLogFile,DWORD attributes)1882 UINT WINAPI MsiEnableLogA( DWORD dwLogMode, const char *szLogFile, DWORD attributes )
1883 {
1884 LPWSTR szwLogFile = NULL;
1885 UINT r;
1886
1887 TRACE( "%#lx, %s, %#lx\n", dwLogMode, debugstr_a(szLogFile), attributes );
1888
1889 if( szLogFile )
1890 {
1891 szwLogFile = strdupAtoW( szLogFile );
1892 if( !szwLogFile )
1893 return ERROR_OUTOFMEMORY;
1894 }
1895 r = MsiEnableLogW( dwLogMode, szwLogFile, attributes );
1896 free( szwLogFile );
1897 return r;
1898 }
1899
MsiEnableLogW(DWORD dwLogMode,const WCHAR * szLogFile,DWORD attributes)1900 UINT WINAPI MsiEnableLogW( DWORD dwLogMode, const WCHAR *szLogFile, DWORD attributes )
1901 {
1902 TRACE( "%#lx, %s, %#lx\n", dwLogMode, debugstr_w(szLogFile), attributes );
1903
1904 free(gszLogFile);
1905 gszLogFile = NULL;
1906 if (szLogFile)
1907 {
1908 HANDLE file;
1909
1910 if (!(attributes & INSTALLLOGATTRIBUTES_APPEND))
1911 DeleteFileW(szLogFile);
1912 file = CreateFileW(szLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
1913 FILE_ATTRIBUTE_NORMAL, NULL);
1914 if (file != INVALID_HANDLE_VALUE)
1915 {
1916 gszLogFile = wcsdup(szLogFile);
1917 CloseHandle(file);
1918 }
1919 else ERR( "unable to enable log %s (%lu)\n", debugstr_w(szLogFile), GetLastError() );
1920 }
1921
1922 return ERROR_SUCCESS;
1923 }
1924
MsiEnumComponentCostsA(MSIHANDLE handle,const char * component,DWORD index,INSTALLSTATE state,char * drive,DWORD * buflen,int * cost,int * temp)1925 UINT WINAPI MsiEnumComponentCostsA( MSIHANDLE handle, const char *component, DWORD index, INSTALLSTATE state,
1926 char *drive, DWORD *buflen, int *cost, int *temp )
1927 {
1928 UINT r;
1929 DWORD len;
1930 WCHAR *driveW, *componentW = NULL;
1931
1932 TRACE( "%lu, %s, %lu, %d, %p, %p, %p, %p\n", handle, debugstr_a(component), index, state, drive, buflen, cost,
1933 temp );
1934
1935 if (!drive || !buflen) return ERROR_INVALID_PARAMETER;
1936 if (component && !(componentW = strdupAtoW( component ))) return ERROR_OUTOFMEMORY;
1937
1938 len = *buflen;
1939 if (!(driveW = malloc( len * sizeof(WCHAR) )))
1940 {
1941 free( componentW );
1942 return ERROR_OUTOFMEMORY;
1943 }
1944 r = MsiEnumComponentCostsW( handle, componentW, index, state, driveW, buflen, cost, temp );
1945 if (!r)
1946 {
1947 WideCharToMultiByte( CP_ACP, 0, driveW, -1, drive, len, NULL, NULL );
1948 }
1949 free( componentW );
1950 free( driveW );
1951 return r;
1952 }
1953
set_drive(WCHAR * buffer,WCHAR letter)1954 static UINT set_drive( WCHAR *buffer, WCHAR letter )
1955 {
1956 buffer[0] = letter;
1957 buffer[1] = ':';
1958 buffer[2] = 0;
1959 return 2;
1960 }
1961
MsiEnumComponentCostsW(MSIHANDLE handle,const WCHAR * component,DWORD index,INSTALLSTATE state,WCHAR * drive,DWORD * buflen,int * cost,int * temp)1962 UINT WINAPI MsiEnumComponentCostsW( MSIHANDLE handle, const WCHAR *component, DWORD index, INSTALLSTATE state,
1963 WCHAR *drive, DWORD *buflen, int *cost, int *temp )
1964 {
1965 UINT r = ERROR_NO_MORE_ITEMS;
1966 MSICOMPONENT *comp = NULL;
1967 MSIPACKAGE *package;
1968 MSIFILE *file;
1969 STATSTG stat = {0};
1970 WCHAR path[MAX_PATH];
1971
1972 TRACE( "%lu, %s, %lu, %d, %p, %p, %p, %p\n", handle, debugstr_w(component), index, state, drive, buflen, cost,
1973 temp );
1974
1975 if (!drive || !buflen || !cost || !temp) return ERROR_INVALID_PARAMETER;
1976 if (!(package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE )))
1977 {
1978 WCHAR buffer[3];
1979 MSIHANDLE remote;
1980
1981 if (!(remote = msi_get_remote(handle)))
1982 return ERROR_INVALID_HANDLE;
1983
1984 __TRY
1985 {
1986 r = remote_EnumComponentCosts(remote, component, index, state, buffer, cost, temp);
1987 }
1988 __EXCEPT(rpc_filter)
1989 {
1990 r = GetExceptionCode();
1991 }
1992 __ENDTRY
1993
1994 if (r == ERROR_SUCCESS)
1995 {
1996 lstrcpynW(drive, buffer, *buflen);
1997 if (*buflen < 3)
1998 r = ERROR_MORE_DATA;
1999 *buflen = 2;
2000 }
2001 return r;
2002 }
2003
2004 if (!msi_get_property_int( package->db, L"CostingComplete", 0 ))
2005 {
2006 msiobj_release( &package->hdr );
2007 return ERROR_FUNCTION_NOT_CALLED;
2008 }
2009 if (component && component[0] && !(comp = msi_get_loaded_component( package, component )))
2010 {
2011 msiobj_release( &package->hdr );
2012 return ERROR_UNKNOWN_COMPONENT;
2013 }
2014 if (*buflen < 3)
2015 {
2016 *buflen = 2;
2017 msiobj_release( &package->hdr );
2018 return ERROR_MORE_DATA;
2019 }
2020 if (index)
2021 {
2022 msiobj_release( &package->hdr );
2023 return ERROR_NO_MORE_ITEMS;
2024 }
2025
2026 drive[0] = 0;
2027 *cost = *temp = 0;
2028 GetWindowsDirectoryW( path, MAX_PATH );
2029 if (component && component[0])
2030 {
2031 if (msi_is_global_assembly( comp )) *temp = comp->cost;
2032 if (!comp->Enabled || !comp->KeyPath)
2033 {
2034 *cost = 0;
2035 *buflen = set_drive( drive, path[0] );
2036 r = ERROR_SUCCESS;
2037 }
2038 else if ((file = msi_get_loaded_file( package, comp->KeyPath )))
2039 {
2040 *cost = comp->cost;
2041 *buflen = set_drive( drive, file->TargetPath[0] );
2042 r = ERROR_SUCCESS;
2043 }
2044 }
2045 else if (IStorage_Stat( package->db->storage, &stat, STATFLAG_NONAME ) == S_OK)
2046 {
2047 *temp = cost_from_size( stat.cbSize.QuadPart );
2048 *buflen = set_drive( drive, path[0] );
2049 r = ERROR_SUCCESS;
2050 }
2051 msiobj_release( &package->hdr );
2052 return r;
2053 }
2054
MsiQueryComponentStateA(LPCSTR szProductCode,LPCSTR szUserSid,MSIINSTALLCONTEXT dwContext,LPCSTR szComponent,INSTALLSTATE * pdwState)2055 UINT WINAPI MsiQueryComponentStateA(LPCSTR szProductCode,
2056 LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext,
2057 LPCSTR szComponent, INSTALLSTATE *pdwState)
2058 {
2059 LPWSTR prodcode = NULL, usersid = NULL, comp = NULL;
2060 UINT r;
2061
2062 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_a(szProductCode),
2063 debugstr_a(szUserSid), dwContext, debugstr_a(szComponent), pdwState);
2064
2065 if (szProductCode && !(prodcode = strdupAtoW(szProductCode)))
2066 return ERROR_OUTOFMEMORY;
2067
2068 if (szUserSid && !(usersid = strdupAtoW(szUserSid)))
2069 return ERROR_OUTOFMEMORY;
2070
2071 if (szComponent && !(comp = strdupAtoW(szComponent)))
2072 return ERROR_OUTOFMEMORY;
2073
2074 r = MsiQueryComponentStateW(prodcode, usersid, dwContext, comp, pdwState);
2075
2076 free(prodcode);
2077 free(usersid);
2078 free(comp);
2079
2080 return r;
2081 }
2082
comp_find_prod_key(const WCHAR * prodcode,MSIINSTALLCONTEXT context)2083 static BOOL comp_find_prod_key(const WCHAR *prodcode, MSIINSTALLCONTEXT context)
2084 {
2085 UINT r;
2086 HKEY hkey = NULL;
2087
2088 r = MSIREG_OpenProductKey(prodcode, NULL, context, &hkey, FALSE);
2089 RegCloseKey(hkey);
2090 return (r == ERROR_SUCCESS);
2091 }
2092
comp_find_package(const WCHAR * prodcode,MSIINSTALLCONTEXT context)2093 static BOOL comp_find_package(const WCHAR *prodcode, MSIINSTALLCONTEXT context)
2094 {
2095 LPCWSTR package;
2096 HKEY hkey;
2097 DWORD sz;
2098 LONG res;
2099 UINT r;
2100
2101 r = MSIREG_OpenInstallProps(prodcode, context, NULL, &hkey, FALSE);
2102 if (r != ERROR_SUCCESS)
2103 return FALSE;
2104
2105 if (context == MSIINSTALLCONTEXT_USERMANAGED)
2106 package = L"ManagedLocalPackage";
2107 else
2108 package = L"LocalPackage";
2109
2110 sz = 0;
2111 res = RegQueryValueExW(hkey, package, NULL, NULL, NULL, &sz);
2112 RegCloseKey(hkey);
2113
2114 return (res == ERROR_SUCCESS);
2115 }
2116
comp_find_prodcode(const WCHAR * squashed_pc,MSIINSTALLCONTEXT context,const WCHAR * comp,WCHAR * val,DWORD * sz)2117 static UINT comp_find_prodcode(const WCHAR *squashed_pc, MSIINSTALLCONTEXT context, const WCHAR *comp, WCHAR *val,
2118 DWORD *sz)
2119 {
2120 HKEY hkey;
2121 LONG res;
2122 UINT r;
2123
2124 if (context == MSIINSTALLCONTEXT_MACHINE)
2125 r = MSIREG_OpenUserDataComponentKey(comp, L"S-1-5-18", &hkey, FALSE);
2126 else
2127 r = MSIREG_OpenUserDataComponentKey(comp, NULL, &hkey, FALSE);
2128
2129 if (r != ERROR_SUCCESS)
2130 return r;
2131
2132 res = RegQueryValueExW( hkey, squashed_pc, NULL, NULL, (BYTE *)val, sz );
2133 if (res != ERROR_SUCCESS)
2134 return res;
2135
2136 RegCloseKey(hkey);
2137 return res;
2138 }
2139
MsiQueryComponentStateW(LPCWSTR szProductCode,LPCWSTR szUserSid,MSIINSTALLCONTEXT dwContext,LPCWSTR szComponent,INSTALLSTATE * pdwState)2140 UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode,
2141 LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext,
2142 LPCWSTR szComponent, INSTALLSTATE *pdwState)
2143 {
2144 WCHAR squashed_pc[SQUASHED_GUID_SIZE];
2145 BOOL found;
2146 DWORD sz;
2147
2148 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_w(szProductCode),
2149 debugstr_w(szUserSid), dwContext, debugstr_w(szComponent), pdwState);
2150
2151 if (!pdwState || !szComponent)
2152 return ERROR_INVALID_PARAMETER;
2153
2154 if (!szProductCode || !*szProductCode || lstrlenW(szProductCode) != GUID_SIZE - 1)
2155 return ERROR_INVALID_PARAMETER;
2156
2157 if (!squash_guid( szProductCode, squashed_pc ))
2158 return ERROR_INVALID_PARAMETER;
2159
2160 found = comp_find_prod_key(szProductCode, dwContext);
2161
2162 if (!comp_find_package(szProductCode, dwContext))
2163 {
2164 if (found)
2165 {
2166 *pdwState = INSTALLSTATE_UNKNOWN;
2167 return ERROR_UNKNOWN_COMPONENT;
2168 }
2169
2170 return ERROR_UNKNOWN_PRODUCT;
2171 }
2172
2173 *pdwState = INSTALLSTATE_UNKNOWN;
2174
2175 sz = 0;
2176 if (comp_find_prodcode( squashed_pc, dwContext, szComponent, NULL, &sz ))
2177 return ERROR_UNKNOWN_COMPONENT;
2178
2179 if (sz == 0)
2180 *pdwState = INSTALLSTATE_NOTUSED;
2181 else
2182 {
2183 WCHAR *val;
2184 UINT r;
2185
2186 if (!(val = malloc( sz ))) return ERROR_OUTOFMEMORY;
2187 if ((r = comp_find_prodcode( squashed_pc, dwContext, szComponent, val, &sz )))
2188 {
2189 free(val);
2190 return r;
2191 }
2192
2193 if (lstrlenW(val) > 2 &&
2194 val[0] >= '0' && val[0] <= '9' && val[1] >= '0' && val[1] <= '9' && val[2] != ':')
2195 {
2196 *pdwState = INSTALLSTATE_SOURCE;
2197 }
2198 else
2199 *pdwState = INSTALLSTATE_LOCAL;
2200 free( val );
2201 }
2202
2203 TRACE("-> %d\n", *pdwState);
2204 return ERROR_SUCCESS;
2205 }
2206
MsiQueryProductStateA(LPCSTR szProduct)2207 INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct)
2208 {
2209 LPWSTR szwProduct = NULL;
2210 INSTALLSTATE r;
2211
2212 if( szProduct )
2213 {
2214 szwProduct = strdupAtoW( szProduct );
2215 if( !szwProduct )
2216 return ERROR_OUTOFMEMORY;
2217 }
2218 r = MsiQueryProductStateW( szwProduct );
2219 free( szwProduct );
2220 return r;
2221 }
2222
MsiQueryProductStateW(LPCWSTR szProduct)2223 INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct)
2224 {
2225 MSIINSTALLCONTEXT context = MSIINSTALLCONTEXT_USERUNMANAGED;
2226 INSTALLSTATE state = INSTALLSTATE_ADVERTISED;
2227 HKEY prodkey = 0, userdata = 0;
2228 DWORD val;
2229 UINT r;
2230
2231 TRACE("%s\n", debugstr_w(szProduct));
2232
2233 if (!szProduct || !*szProduct)
2234 return INSTALLSTATE_INVALIDARG;
2235
2236 if (lstrlenW(szProduct) != GUID_SIZE - 1)
2237 return INSTALLSTATE_INVALIDARG;
2238
2239 if (szProduct[0] != '{' || szProduct[37] != '}')
2240 return INSTALLSTATE_UNKNOWN;
2241
2242 SetLastError( ERROR_SUCCESS );
2243
2244 if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
2245 &prodkey, FALSE) != ERROR_SUCCESS &&
2246 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2247 &prodkey, FALSE) != ERROR_SUCCESS &&
2248 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
2249 &prodkey, FALSE) == ERROR_SUCCESS)
2250 {
2251 context = MSIINSTALLCONTEXT_MACHINE;
2252 }
2253
2254 r = MSIREG_OpenInstallProps(szProduct, context, NULL, &userdata, FALSE);
2255 if (r != ERROR_SUCCESS)
2256 goto done;
2257
2258 if (!msi_reg_get_val_dword(userdata, L"WindowsInstaller", &val))
2259 goto done;
2260
2261 if (val)
2262 state = INSTALLSTATE_DEFAULT;
2263 else
2264 state = INSTALLSTATE_UNKNOWN;
2265
2266 done:
2267 if (!prodkey)
2268 {
2269 state = INSTALLSTATE_UNKNOWN;
2270
2271 if (userdata)
2272 state = INSTALLSTATE_ABSENT;
2273 }
2274
2275 RegCloseKey(prodkey);
2276 RegCloseKey(userdata);
2277 TRACE("-> %d\n", state);
2278 return state;
2279 }
2280
MsiSetInternalUI(INSTALLUILEVEL dwUILevel,HWND * phWnd)2281 INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd)
2282 {
2283 INSTALLUILEVEL old = gUILevel;
2284 HWND oldwnd = gUIhwnd;
2285
2286 TRACE("%08x %p\n", dwUILevel, phWnd);
2287
2288 if (dwUILevel & ~(INSTALLUILEVEL_MASK|INSTALLUILEVEL_HIDECANCEL|INSTALLUILEVEL_PROGRESSONLY|
2289 INSTALLUILEVEL_ENDDIALOG|INSTALLUILEVEL_SOURCERESONLY))
2290 {
2291 FIXME("Unrecognized flags %08x\n", dwUILevel);
2292 return INSTALLUILEVEL_NOCHANGE;
2293 }
2294
2295 if (dwUILevel != INSTALLUILEVEL_NOCHANGE)
2296 gUILevel = dwUILevel;
2297
2298 if (phWnd)
2299 {
2300 gUIhwnd = *phWnd;
2301 *phWnd = oldwnd;
2302 }
2303 return old;
2304 }
2305
MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler,DWORD dwMessageFilter,void * pvContext)2306 INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA( INSTALLUI_HANDLERA puiHandler, DWORD dwMessageFilter, void *pvContext )
2307 {
2308 INSTALLUI_HANDLERA prev = gUIHandlerA;
2309
2310 TRACE( "%p, %#lx, %p\n", puiHandler, dwMessageFilter, pvContext );
2311
2312 gUIHandlerA = puiHandler;
2313 gUIHandlerW = NULL;
2314 gUIFilter = dwMessageFilter;
2315 gUIContext = pvContext;
2316
2317 return prev;
2318 }
2319
MsiSetExternalUIW(INSTALLUI_HANDLERW puiHandler,DWORD dwMessageFilter,void * pvContext)2320 INSTALLUI_HANDLERW WINAPI MsiSetExternalUIW( INSTALLUI_HANDLERW puiHandler, DWORD dwMessageFilter, void *pvContext )
2321 {
2322 INSTALLUI_HANDLERW prev = gUIHandlerW;
2323
2324 TRACE( "%p, %#lx, %p\n", puiHandler, dwMessageFilter, pvContext );
2325
2326 gUIHandlerA = NULL;
2327 gUIHandlerW = puiHandler;
2328 gUIFilter = dwMessageFilter;
2329 gUIContext = pvContext;
2330
2331 return prev;
2332 }
2333
2334 /******************************************************************
2335 * MsiLoadStringW [MSI.@]
2336 *
2337 * Loads a string from MSI's string resources.
2338 *
2339 * PARAMS
2340 *
2341 * handle [I] only -1 is handled currently
2342 * id [I] id of the string to be loaded
2343 * lpBuffer [O] buffer for the string to be written to
2344 * nBufferMax [I] maximum size of the buffer in characters
2345 * lang [I] the preferred language for the string
2346 *
2347 * RETURNS
2348 *
2349 * If successful, this function returns the language id of the string loaded
2350 * If the function fails, the function returns zero.
2351 *
2352 * NOTES
2353 *
2354 * The type of the first parameter is unknown. LoadString's prototype
2355 * suggests that it might be a module handle. I have made it an MSI handle
2356 * for starters, as -1 is an invalid MSI handle, but not an invalid module
2357 * handle. Maybe strings can be stored in an MSI database somehow.
2358 */
MsiLoadStringW(MSIHANDLE handle,UINT id,WCHAR * lpBuffer,int nBufferMax,LANGID lang)2359 LANGID WINAPI MsiLoadStringW( MSIHANDLE handle, UINT id, WCHAR *lpBuffer, int nBufferMax, LANGID lang )
2360 {
2361 HRSRC hres;
2362 HGLOBAL hResData;
2363 LPWSTR p;
2364 DWORD i, len;
2365
2366 TRACE( "%lu, %u, %p, %d, %#x\n", handle, id, lpBuffer, nBufferMax, lang );
2367
2368 if( handle != -1 )
2369 FIXME( "don't know how to deal with handle = %lu\n", handle );
2370
2371 if( !lang )
2372 lang = GetUserDefaultLangID();
2373
2374 hres = FindResourceExW( msi_hInstance, (const WCHAR *)RT_STRING, (WCHAR *)1, lang );
2375 if( !hres )
2376 return 0;
2377 hResData = LoadResource( msi_hInstance, hres );
2378 if( !hResData )
2379 return 0;
2380 p = LockResource( hResData );
2381 if( !p )
2382 return 0;
2383
2384 for (i = 0; i < (id & 0xf); i++) p += *p + 1;
2385 len = *p;
2386
2387 if( nBufferMax <= len )
2388 return 0;
2389
2390 memcpy( lpBuffer, p+1, len * sizeof(WCHAR));
2391 lpBuffer[ len ] = 0;
2392
2393 TRACE("found -> %s\n", debugstr_w(lpBuffer));
2394 return lang;
2395 }
2396
MsiLoadStringA(MSIHANDLE handle,UINT id,LPSTR lpBuffer,int nBufferMax,LANGID lang)2397 LANGID WINAPI MsiLoadStringA( MSIHANDLE handle, UINT id, LPSTR lpBuffer,
2398 int nBufferMax, LANGID lang )
2399 {
2400 LPWSTR bufW;
2401 LANGID r;
2402 INT len;
2403
2404 bufW = malloc(nBufferMax * sizeof(WCHAR));
2405 r = MsiLoadStringW(handle, id, bufW, nBufferMax, lang);
2406 if( r )
2407 {
2408 len = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL );
2409 if( len <= nBufferMax )
2410 WideCharToMultiByte( CP_ACP, 0, bufW, -1,
2411 lpBuffer, nBufferMax, NULL, NULL );
2412 else
2413 r = 0;
2414 }
2415 free(bufW);
2416 return r;
2417 }
2418
MsiLocateComponentA(LPCSTR szComponent,LPSTR lpPathBuf,LPDWORD pcchBuf)2419 INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf,
2420 LPDWORD pcchBuf)
2421 {
2422 char szProduct[GUID_SIZE];
2423
2424 TRACE("%s %p %p\n", debugstr_a(szComponent), lpPathBuf, pcchBuf);
2425
2426 if (!szComponent || !pcchBuf)
2427 return INSTALLSTATE_INVALIDARG;
2428
2429 if (MsiGetProductCodeA( szComponent, szProduct ) != ERROR_SUCCESS)
2430 return INSTALLSTATE_UNKNOWN;
2431
2432 return MsiGetComponentPathA( szProduct, szComponent, lpPathBuf, pcchBuf );
2433 }
2434
MsiLocateComponentW(LPCWSTR szComponent,LPWSTR lpPathBuf,LPDWORD pcchBuf)2435 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPWSTR lpPathBuf,
2436 LPDWORD pcchBuf)
2437 {
2438 WCHAR szProduct[GUID_SIZE];
2439
2440 TRACE("%s %p %p\n", debugstr_w(szComponent), lpPathBuf, pcchBuf);
2441
2442 if (!szComponent || !pcchBuf)
2443 return INSTALLSTATE_INVALIDARG;
2444
2445 if (MsiGetProductCodeW( szComponent, szProduct ) != ERROR_SUCCESS)
2446 return INSTALLSTATE_UNKNOWN;
2447
2448 return MsiGetComponentPathW( szProduct, szComponent, lpPathBuf, pcchBuf );
2449 }
2450
MsiMessageBoxA(HWND hWnd,const char * lpText,const char * lpCaption,UINT uType,WORD wLanguageId,DWORD f)2451 UINT WINAPI MsiMessageBoxA( HWND hWnd, const char *lpText, const char *lpCaption, UINT uType, WORD wLanguageId,
2452 DWORD f )
2453 {
2454 FIXME( "%p, %s, %s, %u, %#x, %#lx\n", hWnd, debugstr_a(lpText), debugstr_a(lpCaption), uType, wLanguageId, f );
2455 return MessageBoxExA( hWnd, lpText, lpCaption, uType, wLanguageId );
2456 }
2457
MsiMessageBoxW(HWND hWnd,const WCHAR * lpText,const WCHAR * lpCaption,UINT uType,WORD wLanguageId,DWORD f)2458 UINT WINAPI MsiMessageBoxW( HWND hWnd, const WCHAR *lpText, const WCHAR *lpCaption, UINT uType, WORD wLanguageId,
2459 DWORD f )
2460 {
2461 FIXME( "%p, %s, %s, %u, %#x %#lx\n", hWnd, debugstr_w(lpText), debugstr_w(lpCaption), uType, wLanguageId, f );
2462 return MessageBoxExW( hWnd, lpText, lpCaption, uType, wLanguageId );
2463 }
2464
MsiMessageBoxExA(HWND hWnd,const char * lpText,const char * lpCaption,UINT uType,DWORD unknown,WORD wLanguageId,DWORD f)2465 UINT WINAPI MsiMessageBoxExA( HWND hWnd, const char *lpText, const char *lpCaption, UINT uType, DWORD unknown,
2466 WORD wLanguageId, DWORD f )
2467 {
2468 FIXME( "%p, %s, %s, %u, %#lx, %#x, %#lx): semi-stub\n", hWnd, debugstr_a(lpText), debugstr_a(lpCaption), uType,
2469 unknown, wLanguageId, f );
2470 return MessageBoxExA( hWnd, lpText, lpCaption, uType, wLanguageId );
2471 }
2472
MsiMessageBoxExW(HWND hWnd,const WCHAR * lpText,const WCHAR * lpCaption,UINT uType,DWORD unknown,WORD wLanguageId,DWORD f)2473 UINT WINAPI MsiMessageBoxExW( HWND hWnd, const WCHAR *lpText, const WCHAR *lpCaption, UINT uType, DWORD unknown,
2474 WORD wLanguageId, DWORD f )
2475 {
2476 FIXME( "%p, %s, %s, %u, %#lx, %#x, %#lx): semi-stub\n", hWnd, debugstr_w(lpText), debugstr_w(lpCaption), uType,
2477 unknown, wLanguageId, f );
2478 return MessageBoxExW( hWnd, lpText, lpCaption, uType, wLanguageId );
2479 }
2480
MsiProvideAssemblyA(const char * szAssemblyName,const char * szAppContext,DWORD dwInstallMode,DWORD dwAssemblyInfo,char * lpPathBuf,DWORD * pcchPathBuf)2481 UINT WINAPI MsiProvideAssemblyA( const char *szAssemblyName, const char *szAppContext, DWORD dwInstallMode,
2482 DWORD dwAssemblyInfo, char *lpPathBuf, DWORD *pcchPathBuf )
2483 {
2484 FIXME( "%s, %s, %#lx, %#lx, %p, %p\n", debugstr_a(szAssemblyName), debugstr_a(szAppContext), dwInstallMode,
2485 dwAssemblyInfo, lpPathBuf, pcchPathBuf );
2486 return ERROR_CALL_NOT_IMPLEMENTED;
2487 }
2488
MsiProvideAssemblyW(const WCHAR * szAssemblyName,const WCHAR * szAppContext,DWORD dwInstallMode,DWORD dwAssemblyInfo,WCHAR * lpPathBuf,DWORD * pcchPathBuf)2489 UINT WINAPI MsiProvideAssemblyW( const WCHAR *szAssemblyName, const WCHAR *szAppContext, DWORD dwInstallMode,
2490 DWORD dwAssemblyInfo, WCHAR *lpPathBuf, DWORD *pcchPathBuf )
2491 {
2492 FIXME( "%s, %s, %#lx, %#lx, %p, %p\n", debugstr_w(szAssemblyName), debugstr_w(szAppContext), dwInstallMode,
2493 dwAssemblyInfo, lpPathBuf, pcchPathBuf );
2494 return ERROR_CALL_NOT_IMPLEMENTED;
2495 }
2496
MsiProvideComponentFromDescriptorA(LPCSTR szDescriptor,LPSTR szPath,LPDWORD pcchPath,LPDWORD pcchArgs)2497 UINT WINAPI MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor,
2498 LPSTR szPath, LPDWORD pcchPath, LPDWORD pcchArgs )
2499 {
2500 FIXME("%s %p %p %p\n", debugstr_a(szDescriptor), szPath, pcchPath, pcchArgs );
2501 return ERROR_CALL_NOT_IMPLEMENTED;
2502 }
2503
MsiProvideComponentFromDescriptorW(LPCWSTR szDescriptor,LPWSTR szPath,LPDWORD pcchPath,LPDWORD pcchArgs)2504 UINT WINAPI MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor,
2505 LPWSTR szPath, LPDWORD pcchPath, LPDWORD pcchArgs )
2506 {
2507 FIXME("%s %p %p %p\n", debugstr_w(szDescriptor), szPath, pcchPath, pcchArgs );
2508 return ERROR_CALL_NOT_IMPLEMENTED;
2509 }
2510
MsiGetFileSignatureInformationA(const char * path,DWORD flags,PCCERT_CONTEXT * cert,BYTE * hash,DWORD * hashlen)2511 HRESULT WINAPI MsiGetFileSignatureInformationA( const char *path, DWORD flags, PCCERT_CONTEXT *cert, BYTE *hash,
2512 DWORD *hashlen )
2513 {
2514 UINT r;
2515 WCHAR *pathW = NULL;
2516
2517 TRACE( "%s, %#lx, %p, %p, %p\n", debugstr_a(path), flags, cert, hash, hashlen );
2518
2519 if (path && !(pathW = strdupAtoW( path ))) return E_OUTOFMEMORY;
2520 r = MsiGetFileSignatureInformationW( pathW, flags, cert, hash, hashlen );
2521 free( pathW );
2522 return r;
2523 }
2524
MsiGetFileSignatureInformationW(const WCHAR * path,DWORD flags,PCCERT_CONTEXT * cert,BYTE * hash,DWORD * hashlen)2525 HRESULT WINAPI MsiGetFileSignatureInformationW( const WCHAR *path, DWORD flags, PCCERT_CONTEXT *cert, BYTE *hash,
2526 DWORD *hashlen )
2527 {
2528 static GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
2529 HRESULT hr;
2530 WINTRUST_DATA data;
2531 WINTRUST_FILE_INFO info;
2532 CRYPT_PROVIDER_SGNR *signer;
2533 CRYPT_PROVIDER_CERT *provider;
2534
2535 TRACE( "%s, %#lx, %p, %p, %p\n", debugstr_w(path), flags, cert, hash, hashlen );
2536
2537 if (!path || !cert) return E_INVALIDARG;
2538
2539 info.cbStruct = sizeof(info);
2540 info.pcwszFilePath = path;
2541 info.hFile = NULL;
2542 info.pgKnownSubject = NULL;
2543
2544 memset( &data, 0, sizeof(data) );
2545 data.cbStruct = sizeof(data);
2546 data.dwUIChoice = WTD_UI_NONE;
2547 data.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN;
2548 data.dwUnionChoice = WTD_CHOICE_FILE;
2549 data.pFile = &info;
2550 data.dwStateAction = WTD_STATEACTION_VERIFY;
2551 data.dwUIContext = WTD_UICONTEXT_INSTALL;
2552
2553 hr = WinVerifyTrustEx( INVALID_HANDLE_VALUE, &generic_verify_v2, &data );
2554 *cert = NULL;
2555 if (FAILED(hr)) goto done;
2556
2557 if (!(signer = WTHelperGetProvSignerFromChain( data.hWVTStateData, 0, FALSE, 0 )))
2558 {
2559 hr = TRUST_E_NOSIGNATURE;
2560 goto done;
2561 }
2562 if (hash)
2563 {
2564 DWORD len = signer->psSigner->EncryptedHash.cbData;
2565 if (*hashlen < len)
2566 {
2567 *hashlen = len;
2568 hr = HRESULT_FROM_WIN32(ERROR_MORE_DATA);
2569 goto done;
2570 }
2571 memcpy( hash, signer->psSigner->EncryptedHash.pbData, len );
2572 *hashlen = len;
2573 }
2574 if (!(provider = WTHelperGetProvCertFromChain( signer, 0 )))
2575 {
2576 hr = TRUST_E_PROVIDER_UNKNOWN;
2577 goto done;
2578 }
2579 *cert = CertDuplicateCertificateContext( provider->pCert );
2580
2581 done:
2582 data.dwStateAction = WTD_STATEACTION_CLOSE;
2583 WinVerifyTrustEx( INVALID_HANDLE_VALUE, &generic_verify_v2, &data );
2584 return hr;
2585 }
2586
2587 /******************************************************************
2588 * MsiGetProductPropertyA [MSI.@]
2589 */
MsiGetProductPropertyA(MSIHANDLE hProduct,const char * szProperty,char * szValue,DWORD * pccbValue)2590 UINT WINAPI MsiGetProductPropertyA( MSIHANDLE hProduct, const char *szProperty, char *szValue, DWORD *pccbValue )
2591 {
2592 LPWSTR prop = NULL, val = NULL;
2593 DWORD len;
2594 UINT r;
2595
2596 TRACE( "%lu, %s, %p, %p\n", hProduct, debugstr_a(szProperty), szValue, pccbValue );
2597
2598 if (szValue && !pccbValue)
2599 return ERROR_INVALID_PARAMETER;
2600
2601 if (szProperty) prop = strdupAtoW(szProperty);
2602
2603 len = 0;
2604 r = MsiGetProductPropertyW(hProduct, prop, NULL, &len);
2605 if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
2606 goto done;
2607
2608 if (r == ERROR_SUCCESS)
2609 {
2610 if (szValue) *szValue = '\0';
2611 if (pccbValue) *pccbValue = 0;
2612 goto done;
2613 }
2614
2615 val = malloc(++len * sizeof(WCHAR));
2616 if (!val)
2617 {
2618 r = ERROR_OUTOFMEMORY;
2619 goto done;
2620 }
2621
2622 r = MsiGetProductPropertyW(hProduct, prop, val, &len);
2623 if (r != ERROR_SUCCESS)
2624 goto done;
2625
2626 len = WideCharToMultiByte(CP_ACP, 0, val, -1, NULL, 0, NULL, NULL);
2627
2628 if (szValue)
2629 WideCharToMultiByte(CP_ACP, 0, val, -1, szValue,
2630 *pccbValue, NULL, NULL);
2631
2632 if (pccbValue)
2633 {
2634 if (len > *pccbValue)
2635 r = ERROR_MORE_DATA;
2636
2637 *pccbValue = len - 1;
2638 }
2639
2640 done:
2641 free(prop);
2642 free(val);
2643
2644 return r;
2645 }
2646
2647 /******************************************************************
2648 * MsiGetProductPropertyW [MSI.@]
2649 */
MsiGetProductPropertyW(MSIHANDLE hProduct,const WCHAR * szProperty,WCHAR * szValue,DWORD * pccbValue)2650 UINT WINAPI MsiGetProductPropertyW( MSIHANDLE hProduct, const WCHAR *szProperty, WCHAR *szValue, DWORD *pccbValue )
2651 {
2652 MSIPACKAGE *package;
2653 MSIQUERY *view = NULL;
2654 MSIRECORD *rec = NULL;
2655 LPCWSTR val;
2656 UINT r;
2657
2658 TRACE( "%lu, %s, %p, %p)\n", hProduct, debugstr_w(szProperty), szValue, pccbValue );
2659
2660 if (!szProperty)
2661 return ERROR_INVALID_PARAMETER;
2662
2663 if (szValue && !pccbValue)
2664 return ERROR_INVALID_PARAMETER;
2665
2666 package = msihandle2msiinfo(hProduct, MSIHANDLETYPE_PACKAGE);
2667 if (!package)
2668 return ERROR_INVALID_HANDLE;
2669
2670 r = MSI_OpenQuery(package->db, &view, L"SELECT * FROM `Property` WHERE `Property` = '%s'", szProperty);
2671 if (r != ERROR_SUCCESS)
2672 goto done;
2673
2674 r = MSI_ViewExecute(view, 0);
2675 if (r != ERROR_SUCCESS)
2676 goto done;
2677
2678 r = MSI_ViewFetch(view, &rec);
2679 if (r != ERROR_SUCCESS)
2680 goto done;
2681
2682 val = MSI_RecordGetString(rec, 2);
2683 if (!val)
2684 goto done;
2685
2686 if (lstrlenW(val) >= *pccbValue)
2687 {
2688 if (szValue) lstrcpynW(szValue, val, *pccbValue);
2689 r = ERROR_MORE_DATA;
2690 }
2691 else
2692 {
2693 if (szValue) lstrcpyW(szValue, val);
2694 r = ERROR_SUCCESS;
2695 }
2696
2697 *pccbValue = lstrlenW(val);
2698
2699 done:
2700 if (view)
2701 {
2702 MSI_ViewClose(view);
2703 msiobj_release(&view->hdr);
2704 if (rec) msiobj_release(&rec->hdr);
2705 }
2706
2707 if (!rec)
2708 {
2709 if (szValue) *szValue = '\0';
2710 if (pccbValue) *pccbValue = 0;
2711 r = ERROR_SUCCESS;
2712 }
2713
2714 msiobj_release(&package->hdr);
2715 return r;
2716 }
2717
MsiVerifyPackageA(LPCSTR szPackage)2718 UINT WINAPI MsiVerifyPackageA( LPCSTR szPackage )
2719 {
2720 UINT r;
2721 LPWSTR szPack = NULL;
2722
2723 TRACE("%s\n", debugstr_a(szPackage) );
2724
2725 if( szPackage )
2726 {
2727 szPack = strdupAtoW( szPackage );
2728 if( !szPack )
2729 return ERROR_OUTOFMEMORY;
2730 }
2731
2732 r = MsiVerifyPackageW( szPack );
2733
2734 free( szPack );
2735
2736 return r;
2737 }
2738
MsiVerifyPackageW(LPCWSTR szPackage)2739 UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage )
2740 {
2741 MSIHANDLE handle;
2742 UINT r;
2743
2744 TRACE("%s\n", debugstr_w(szPackage) );
2745
2746 r = MsiOpenDatabaseW( szPackage, MSIDBOPEN_READONLY, &handle );
2747 MsiCloseHandle( handle );
2748
2749 return r;
2750 }
2751
open_userdata_comp_key(const WCHAR * comp,const WCHAR * usersid,MSIINSTALLCONTEXT ctx,HKEY * hkey)2752 static BOOL open_userdata_comp_key( const WCHAR *comp, const WCHAR *usersid, MSIINSTALLCONTEXT ctx,
2753 HKEY *hkey )
2754 {
2755 if (ctx & MSIINSTALLCONTEXT_MACHINE)
2756 {
2757 if (!MSIREG_OpenUserDataComponentKey( comp, L"S-1-5-18", hkey, FALSE )) return TRUE;
2758 }
2759 if (ctx & (MSIINSTALLCONTEXT_USERMANAGED|MSIINSTALLCONTEXT_USERUNMANAGED))
2760 {
2761 if (usersid && !wcsicmp( usersid, L"S-1-1-0" ))
2762 {
2763 FIXME( "only looking at the current user\n" );
2764 usersid = NULL;
2765 }
2766 if (!MSIREG_OpenUserDataComponentKey( comp, usersid, hkey, FALSE )) return TRUE;
2767 }
2768 return FALSE;
2769 }
2770
MSI_GetComponentPath(const WCHAR * szProduct,const WCHAR * szComponent,const WCHAR * szUserSid,MSIINSTALLCONTEXT ctx,awstring * lpPathBuf,DWORD * pcchBuf)2771 static INSTALLSTATE MSI_GetComponentPath( const WCHAR *szProduct, const WCHAR *szComponent,
2772 const WCHAR *szUserSid, MSIINSTALLCONTEXT ctx,
2773 awstring *lpPathBuf, DWORD *pcchBuf )
2774 {
2775 WCHAR *path = NULL, squashed_pc[SQUASHED_GUID_SIZE], squashed_comp[SQUASHED_GUID_SIZE];
2776 HKEY hkey;
2777 INSTALLSTATE state;
2778 DWORD version;
2779
2780 if (!szProduct || !szComponent)
2781 return INSTALLSTATE_INVALIDARG;
2782
2783 if (lpPathBuf->str.w && !pcchBuf)
2784 return INSTALLSTATE_INVALIDARG;
2785
2786 if (!squash_guid( szProduct, squashed_pc ) || !squash_guid( szComponent, squashed_comp ))
2787 return INSTALLSTATE_INVALIDARG;
2788
2789 if (szUserSid && ctx == MSIINSTALLCONTEXT_MACHINE)
2790 return INSTALLSTATE_INVALIDARG;
2791
2792 state = INSTALLSTATE_UNKNOWN;
2793
2794 if (open_userdata_comp_key( szComponent, szUserSid, ctx, &hkey ))
2795 {
2796 path = msi_reg_get_val_str( hkey, squashed_pc );
2797 RegCloseKey(hkey);
2798
2799 state = INSTALLSTATE_ABSENT;
2800
2801 if ((!MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE, NULL, &hkey, FALSE) ||
2802 !MSIREG_OpenUserDataProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED, NULL, &hkey, FALSE)) &&
2803 msi_reg_get_val_dword(hkey, L"WindowsInstaller", &version) &&
2804 GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES)
2805 {
2806 RegCloseKey(hkey);
2807 state = INSTALLSTATE_LOCAL;
2808 }
2809 }
2810
2811 if (state != INSTALLSTATE_LOCAL &&
2812 (!MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, &hkey, FALSE) ||
2813 !MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE, &hkey, FALSE)))
2814 {
2815 RegCloseKey(hkey);
2816
2817 if (open_userdata_comp_key( szComponent, szUserSid, ctx, &hkey ))
2818 {
2819 free(path);
2820 path = msi_reg_get_val_str( hkey, squashed_pc );
2821 RegCloseKey(hkey);
2822
2823 state = INSTALLSTATE_ABSENT;
2824
2825 if (GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES)
2826 state = INSTALLSTATE_LOCAL;
2827 }
2828 }
2829
2830 if (!path)
2831 return INSTALLSTATE_UNKNOWN;
2832
2833 if (state == INSTALLSTATE_LOCAL && !*path)
2834 state = INSTALLSTATE_NOTUSED;
2835
2836 if (msi_strcpy_to_awstring(path, -1, lpPathBuf, pcchBuf) == ERROR_MORE_DATA)
2837 state = INSTALLSTATE_MOREDATA;
2838
2839 free(path);
2840 return state;
2841 }
2842
2843 /******************************************************************
2844 * MsiGetComponentPathExW [MSI.@]
2845 */
MsiGetComponentPathExW(LPCWSTR product,LPCWSTR comp,LPCWSTR usersid,MSIINSTALLCONTEXT ctx,LPWSTR buf,LPDWORD buflen)2846 INSTALLSTATE WINAPI MsiGetComponentPathExW( LPCWSTR product, LPCWSTR comp, LPCWSTR usersid,
2847 MSIINSTALLCONTEXT ctx, LPWSTR buf, LPDWORD buflen )
2848 {
2849 awstring path;
2850
2851 TRACE( "%s %s %s 0x%x %p %p\n", debugstr_w(product), debugstr_w(comp), debugstr_w(usersid),
2852 ctx, buf, buflen );
2853
2854 path.unicode = TRUE;
2855 path.str.w = buf;
2856
2857 return MSI_GetComponentPath( product, comp, usersid, ctx, &path, buflen );
2858 }
2859
MsiGetComponentPathExA(LPCSTR product,LPCSTR comp,LPCSTR usersid,MSIINSTALLCONTEXT ctx,LPSTR buf,LPDWORD buflen)2860 INSTALLSTATE WINAPI MsiGetComponentPathExA( LPCSTR product, LPCSTR comp, LPCSTR usersid,
2861 MSIINSTALLCONTEXT ctx, LPSTR buf, LPDWORD buflen )
2862 {
2863 WCHAR *productW = NULL, *compW = NULL, *usersidW = NULL;
2864 INSTALLSTATE r = INSTALLSTATE_UNKNOWN;
2865 awstring path;
2866
2867 TRACE( "%s %s %s 0x%x %p %p\n", debugstr_a(product), debugstr_a(comp), debugstr_a(usersid),
2868 ctx, buf, buflen );
2869
2870 if (product && !(productW = strdupAtoW( product ))) return INSTALLSTATE_UNKNOWN;
2871 if (comp && !(compW = strdupAtoW( comp ))) goto end;
2872 if (usersid && !(usersidW = strdupAtoW( usersid ))) goto end;
2873
2874 path.unicode = FALSE;
2875 path.str.a = buf;
2876
2877 r = MSI_GetComponentPath( productW, compW, usersidW, ctx, &path, buflen );
2878
2879 end:
2880 free( productW );
2881 free( compW );
2882 free( usersidW );
2883
2884 return r;
2885 }
2886
2887 /******************************************************************
2888 * MsiGetComponentPathW [MSI.@]
2889 */
MsiGetComponentPathW(LPCWSTR product,LPCWSTR comp,LPWSTR buf,LPDWORD buflen)2890 INSTALLSTATE WINAPI MsiGetComponentPathW( LPCWSTR product, LPCWSTR comp, LPWSTR buf, LPDWORD buflen )
2891 {
2892 return MsiGetComponentPathExW( product, comp, L"S-1-1-0", MSIINSTALLCONTEXT_ALL, buf, buflen );
2893 }
2894
2895 /******************************************************************
2896 * MsiGetComponentPathA [MSI.@]
2897 */
MsiGetComponentPathA(LPCSTR product,LPCSTR comp,LPSTR buf,LPDWORD buflen)2898 INSTALLSTATE WINAPI MsiGetComponentPathA( LPCSTR product, LPCSTR comp, LPSTR buf, LPDWORD buflen )
2899 {
2900 return MsiGetComponentPathExA( product, comp, "s-1-1-0", MSIINSTALLCONTEXT_ALL, buf, buflen );
2901 }
2902
query_feature_state(const WCHAR * product,const WCHAR * squashed,const WCHAR * usersid,MSIINSTALLCONTEXT ctx,const WCHAR * feature,INSTALLSTATE * state)2903 static UINT query_feature_state( const WCHAR *product, const WCHAR *squashed, const WCHAR *usersid,
2904 MSIINSTALLCONTEXT ctx, const WCHAR *feature, INSTALLSTATE *state )
2905 {
2906 UINT r;
2907 HKEY hkey;
2908 WCHAR *parent, *components, *path;
2909 const WCHAR *p;
2910 BOOL missing = FALSE, source = FALSE;
2911 WCHAR comp[GUID_SIZE];
2912 GUID guid;
2913
2914 if (ctx != MSIINSTALLCONTEXT_MACHINE) SetLastError( ERROR_SUCCESS );
2915
2916 if (MSIREG_OpenFeaturesKey( product, usersid, ctx, &hkey, FALSE )) return ERROR_UNKNOWN_PRODUCT;
2917
2918 parent = msi_reg_get_val_str( hkey, feature );
2919 RegCloseKey( hkey );
2920 if (!parent) return ERROR_UNKNOWN_FEATURE;
2921
2922 *state = (parent[0] == 6) ? INSTALLSTATE_ABSENT : INSTALLSTATE_LOCAL;
2923 free( parent );
2924 if (*state == INSTALLSTATE_ABSENT)
2925 return ERROR_SUCCESS;
2926
2927 r = MSIREG_OpenUserDataFeaturesKey( product, usersid, ctx, &hkey, FALSE );
2928 if (r != ERROR_SUCCESS)
2929 {
2930 *state = INSTALLSTATE_ADVERTISED;
2931 return ERROR_SUCCESS;
2932 }
2933 components = msi_reg_get_val_str( hkey, feature );
2934 RegCloseKey( hkey );
2935
2936 TRACE("buffer = %s\n", debugstr_w(components));
2937
2938 if (!components)
2939 {
2940 *state = INSTALLSTATE_ADVERTISED;
2941 return ERROR_SUCCESS;
2942 }
2943 for (p = components; *p && *p != 2 ; p += 20)
2944 {
2945 if (!decode_base85_guid( p, &guid ))
2946 {
2947 if (p != components) break;
2948 free( components );
2949 *state = INSTALLSTATE_BADCONFIG;
2950 return ERROR_BAD_CONFIGURATION;
2951 }
2952 StringFromGUID2( &guid, comp, GUID_SIZE );
2953 if (ctx == MSIINSTALLCONTEXT_MACHINE)
2954 r = MSIREG_OpenUserDataComponentKey( comp, L"S-1-5-18", &hkey, FALSE );
2955 else
2956 r = MSIREG_OpenUserDataComponentKey( comp, usersid, &hkey, FALSE );
2957
2958 if (r != ERROR_SUCCESS)
2959 {
2960 free( components );
2961 *state = INSTALLSTATE_ADVERTISED;
2962 return ERROR_SUCCESS;
2963 }
2964 path = msi_reg_get_val_str( hkey, squashed );
2965 if (!path) missing = TRUE;
2966 else if (lstrlenW( path ) > 2 &&
2967 path[0] >= '0' && path[0] <= '9' &&
2968 path[1] >= '0' && path[1] <= '9')
2969 {
2970 source = TRUE;
2971 }
2972 free( path );
2973 }
2974 free( components );
2975
2976 if (missing)
2977 *state = INSTALLSTATE_ADVERTISED;
2978 else if (source)
2979 *state = INSTALLSTATE_SOURCE;
2980 else
2981 *state = INSTALLSTATE_LOCAL;
2982
2983 TRACE("returning state %d\n", *state);
2984 return ERROR_SUCCESS;
2985 }
2986
MsiQueryFeatureStateExA(LPCSTR product,LPCSTR usersid,MSIINSTALLCONTEXT ctx,LPCSTR feature,INSTALLSTATE * state)2987 UINT WINAPI MsiQueryFeatureStateExA( LPCSTR product, LPCSTR usersid, MSIINSTALLCONTEXT ctx,
2988 LPCSTR feature, INSTALLSTATE *state )
2989 {
2990 UINT r;
2991 WCHAR *productW = NULL, *usersidW = NULL, *featureW = NULL;
2992
2993 if (product && !(productW = strdupAtoW( product ))) return ERROR_OUTOFMEMORY;
2994 if (usersid && !(usersidW = strdupAtoW( usersid )))
2995 {
2996 free( productW );
2997 return ERROR_OUTOFMEMORY;
2998 }
2999 if (feature && !(featureW = strdupAtoW( feature )))
3000 {
3001 free( productW );
3002 free( usersidW );
3003 return ERROR_OUTOFMEMORY;
3004 }
3005 r = MsiQueryFeatureStateExW( productW, usersidW, ctx, featureW, state );
3006 free( productW );
3007 free( usersidW );
3008 free( featureW );
3009 return r;
3010 }
3011
MsiQueryFeatureStateExW(LPCWSTR product,LPCWSTR usersid,MSIINSTALLCONTEXT ctx,LPCWSTR feature,INSTALLSTATE * state)3012 UINT WINAPI MsiQueryFeatureStateExW( LPCWSTR product, LPCWSTR usersid, MSIINSTALLCONTEXT ctx,
3013 LPCWSTR feature, INSTALLSTATE *state )
3014 {
3015 WCHAR squashed[33];
3016 if (!squash_guid( product, squashed )) return ERROR_INVALID_PARAMETER;
3017 return query_feature_state( product, squashed, usersid, ctx, feature, state );
3018 }
3019
3020 /******************************************************************
3021 * MsiQueryFeatureStateA [MSI.@]
3022 */
MsiQueryFeatureStateA(LPCSTR szProduct,LPCSTR szFeature)3023 INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature)
3024 {
3025 LPWSTR szwProduct = NULL, szwFeature= NULL;
3026 INSTALLSTATE rc = INSTALLSTATE_UNKNOWN;
3027
3028 szwProduct = strdupAtoW( szProduct );
3029 if ( szProduct && !szwProduct )
3030 goto end;
3031
3032 szwFeature = strdupAtoW( szFeature );
3033 if ( szFeature && !szwFeature )
3034 goto end;
3035
3036 rc = MsiQueryFeatureStateW(szwProduct, szwFeature);
3037
3038 end:
3039 free(szwProduct);
3040 free(szwFeature);
3041
3042 return rc;
3043 }
3044
3045 /******************************************************************
3046 * MsiQueryFeatureStateW [MSI.@]
3047 *
3048 * Checks the state of a feature
3049 *
3050 * PARAMS
3051 * szProduct [I] Product's GUID string
3052 * szFeature [I] Feature's GUID string
3053 *
3054 * RETURNS
3055 * INSTALLSTATE_LOCAL Feature is installed and usable
3056 * INSTALLSTATE_ABSENT Feature is absent
3057 * INSTALLSTATE_ADVERTISED Feature should be installed on demand
3058 * INSTALLSTATE_UNKNOWN An error occurred
3059 * INSTALLSTATE_INVALIDARG One of the GUIDs was invalid
3060 *
3061 */
MsiQueryFeatureStateW(LPCWSTR szProduct,LPCWSTR szFeature)3062 INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature)
3063 {
3064 UINT r;
3065 INSTALLSTATE state;
3066 WCHAR squashed[33];
3067
3068 TRACE("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature));
3069
3070 if (!szProduct || !szFeature || !squash_guid( szProduct, squashed ))
3071 return INSTALLSTATE_INVALIDARG;
3072
3073 r = query_feature_state( szProduct, squashed, NULL, MSIINSTALLCONTEXT_USERMANAGED, szFeature, &state );
3074 if (r == ERROR_SUCCESS || r == ERROR_BAD_CONFIGURATION) return state;
3075
3076 r = query_feature_state( szProduct, squashed, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, szFeature, &state );
3077 if (r == ERROR_SUCCESS || r == ERROR_BAD_CONFIGURATION) return state;
3078
3079 r = query_feature_state( szProduct, squashed, NULL, MSIINSTALLCONTEXT_MACHINE, szFeature, &state );
3080 if (r == ERROR_SUCCESS || r == ERROR_BAD_CONFIGURATION) return state;
3081
3082 return INSTALLSTATE_UNKNOWN;
3083 }
3084
3085 /******************************************************************
3086 * MsiGetFileVersionA [MSI.@]
3087 */
MsiGetFileVersionA(LPCSTR szFilePath,LPSTR lpVersionBuf,LPDWORD pcchVersionBuf,LPSTR lpLangBuf,LPDWORD pcchLangBuf)3088 UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf,
3089 LPDWORD pcchVersionBuf, LPSTR lpLangBuf, LPDWORD pcchLangBuf)
3090 {
3091 LPWSTR szwFilePath = NULL, lpwVersionBuff = NULL, lpwLangBuff = NULL;
3092 UINT ret = ERROR_OUTOFMEMORY;
3093
3094 if ((lpVersionBuf && !pcchVersionBuf) ||
3095 (lpLangBuf && !pcchLangBuf))
3096 return ERROR_INVALID_PARAMETER;
3097
3098 if( szFilePath )
3099 {
3100 szwFilePath = strdupAtoW( szFilePath );
3101 if( !szwFilePath )
3102 goto end;
3103 }
3104
3105 if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf )
3106 {
3107 lpwVersionBuff = malloc(*pcchVersionBuf * sizeof(WCHAR));
3108 if( !lpwVersionBuff )
3109 goto end;
3110 }
3111
3112 if( lpLangBuf && pcchLangBuf && *pcchLangBuf )
3113 {
3114 lpwLangBuff = malloc(*pcchLangBuf * sizeof(WCHAR));
3115 if( !lpwLangBuff )
3116 goto end;
3117 }
3118
3119 ret = MsiGetFileVersionW(szwFilePath, lpwVersionBuff, pcchVersionBuf,
3120 lpwLangBuff, pcchLangBuf);
3121
3122 if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwVersionBuff )
3123 WideCharToMultiByte(CP_ACP, 0, lpwVersionBuff, -1,
3124 lpVersionBuf, *pcchVersionBuf + 1, NULL, NULL);
3125 if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwLangBuff )
3126 WideCharToMultiByte(CP_ACP, 0, lpwLangBuff, -1,
3127 lpLangBuf, *pcchLangBuf + 1, NULL, NULL);
3128
3129 end:
3130 free(szwFilePath);
3131 free(lpwVersionBuff);
3132 free(lpwLangBuff);
3133
3134 return ret;
3135 }
3136
get_file_version(const WCHAR * path,WCHAR * verbuf,DWORD * verlen,WCHAR * langbuf,DWORD * langlen)3137 static UINT get_file_version( const WCHAR *path, WCHAR *verbuf, DWORD *verlen,
3138 WCHAR *langbuf, DWORD *langlen )
3139 {
3140 UINT ret = ERROR_MORE_DATA;
3141 UINT len;
3142 DWORD error;
3143 LPVOID version;
3144 VS_FIXEDFILEINFO *ffi;
3145 USHORT *lang;
3146 WCHAR tmp[32];
3147
3148 if (!(len = GetFileVersionInfoSizeW( path, NULL )))
3149 {
3150 error = GetLastError();
3151 if (error == ERROR_BAD_PATHNAME) return ERROR_FILE_NOT_FOUND;
3152 if (error == ERROR_RESOURCE_DATA_NOT_FOUND) return ERROR_FILE_INVALID;
3153 return error;
3154 }
3155 if (!(version = malloc( len ))) return ERROR_OUTOFMEMORY;
3156 if (!GetFileVersionInfoW( path, 0, len, version ))
3157 {
3158 free( version );
3159 return GetLastError();
3160 }
3161 if (!verbuf && !verlen && !langbuf && !langlen)
3162 {
3163 free( version );
3164 return ERROR_SUCCESS;
3165 }
3166 if (verlen)
3167 {
3168 if (VerQueryValueW( version, L"\\", (LPVOID *)&ffi, &len ) && len > 0)
3169 {
3170 swprintf( tmp, ARRAY_SIZE(tmp), L"%d.%d.%d.%d",
3171 HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS),
3172 HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS) );
3173 if (verbuf) lstrcpynW( verbuf, tmp, *verlen );
3174 len = lstrlenW( tmp );
3175 if (*verlen > len) ret = ERROR_SUCCESS;
3176 *verlen = len;
3177 }
3178 else
3179 {
3180 if (verbuf) *verbuf = 0;
3181 *verlen = 0;
3182 }
3183 }
3184 if (langlen)
3185 {
3186 if (VerQueryValueW( version, L"\\VarFileInfo\\Translation", (LPVOID *)&lang, &len ) && len > 0)
3187 {
3188 swprintf( tmp, ARRAY_SIZE(tmp), L"%d", *lang );
3189 if (langbuf) lstrcpynW( langbuf, tmp, *langlen );
3190 len = lstrlenW( tmp );
3191 if (*langlen > len) ret = ERROR_SUCCESS;
3192 *langlen = len;
3193 }
3194 else
3195 {
3196 if (langbuf) *langbuf = 0;
3197 *langlen = 0;
3198 }
3199 }
3200 free( version );
3201 return ret;
3202 }
3203
3204
3205 /******************************************************************
3206 * MsiGetFileVersionW [MSI.@]
3207 */
MsiGetFileVersionW(const WCHAR * path,WCHAR * verbuf,DWORD * verlen,WCHAR * langbuf,DWORD * langlen)3208 UINT WINAPI MsiGetFileVersionW( const WCHAR *path, WCHAR *verbuf, DWORD *verlen, WCHAR *langbuf, DWORD *langlen )
3209 {
3210 UINT ret;
3211
3212 TRACE( "%s, %p(%lu), %p(%lu)\n", debugstr_w(path), verbuf, verlen ? *verlen : 0, langbuf, langlen ? *langlen : 0 );
3213
3214 if ((verbuf && !verlen) || (langbuf && !langlen))
3215 return ERROR_INVALID_PARAMETER;
3216
3217 ret = get_file_version( path, verbuf, verlen, langbuf, langlen );
3218 if (ret == ERROR_RESOURCE_DATA_NOT_FOUND && verlen)
3219 {
3220 int len;
3221 WCHAR *version = msi_get_font_file_version( NULL, path );
3222 if (!version) return ERROR_FILE_INVALID;
3223 len = lstrlenW( version );
3224 if (len >= *verlen) ret = ERROR_MORE_DATA;
3225 else if (verbuf)
3226 {
3227 lstrcpyW( verbuf, version );
3228 ret = ERROR_SUCCESS;
3229 }
3230 *verlen = len;
3231 free( version );
3232 }
3233 return ret;
3234 }
3235
3236 /***********************************************************************
3237 * MsiGetFeatureUsageW [MSI.@]
3238 */
MsiGetFeatureUsageW(LPCWSTR szProduct,LPCWSTR szFeature,LPDWORD pdwUseCount,LPWORD pwDateUsed)3239 UINT WINAPI MsiGetFeatureUsageW( LPCWSTR szProduct, LPCWSTR szFeature,
3240 LPDWORD pdwUseCount, LPWORD pwDateUsed )
3241 {
3242 FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szFeature),
3243 pdwUseCount, pwDateUsed);
3244 return ERROR_CALL_NOT_IMPLEMENTED;
3245 }
3246
3247 /***********************************************************************
3248 * MsiGetFeatureUsageA [MSI.@]
3249 */
MsiGetFeatureUsageA(LPCSTR szProduct,LPCSTR szFeature,LPDWORD pdwUseCount,LPWORD pwDateUsed)3250 UINT WINAPI MsiGetFeatureUsageA( LPCSTR szProduct, LPCSTR szFeature,
3251 LPDWORD pdwUseCount, LPWORD pwDateUsed )
3252 {
3253 LPWSTR prod = NULL, feat = NULL;
3254 UINT ret = ERROR_OUTOFMEMORY;
3255
3256 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szFeature),
3257 pdwUseCount, pwDateUsed);
3258
3259 prod = strdupAtoW( szProduct );
3260 if (szProduct && !prod)
3261 goto end;
3262
3263 feat = strdupAtoW( szFeature );
3264 if (szFeature && !feat)
3265 goto end;
3266
3267 ret = MsiGetFeatureUsageW( prod, feat, pdwUseCount, pwDateUsed );
3268
3269 end:
3270 free( prod );
3271 free( feat );
3272
3273 return ret;
3274 }
3275
3276 /***********************************************************************
3277 * MsiUseFeatureExW [MSI.@]
3278 */
MsiUseFeatureExW(const WCHAR * szProduct,const WCHAR * szFeature,DWORD dwInstallMode,DWORD dwReserved)3279 INSTALLSTATE WINAPI MsiUseFeatureExW( const WCHAR *szProduct, const WCHAR *szFeature, DWORD dwInstallMode,
3280 DWORD dwReserved )
3281 {
3282 INSTALLSTATE state;
3283
3284 TRACE( "%s, %s, %lu %#lx\n", debugstr_w(szProduct), debugstr_w(szFeature), dwInstallMode, dwReserved );
3285
3286 state = MsiQueryFeatureStateW( szProduct, szFeature );
3287
3288 if (dwReserved)
3289 return INSTALLSTATE_INVALIDARG;
3290
3291 if (state == INSTALLSTATE_LOCAL && dwInstallMode != INSTALLMODE_NODETECTION)
3292 {
3293 FIXME("mark product %s feature %s as used\n",
3294 debugstr_w(szProduct), debugstr_w(szFeature) );
3295 }
3296
3297 return state;
3298 }
3299
3300 /***********************************************************************
3301 * MsiUseFeatureExA [MSI.@]
3302 */
MsiUseFeatureExA(const char * szProduct,const char * szFeature,DWORD dwInstallMode,DWORD dwReserved)3303 INSTALLSTATE WINAPI MsiUseFeatureExA( const char *szProduct, const char *szFeature, DWORD dwInstallMode,
3304 DWORD dwReserved )
3305 {
3306 INSTALLSTATE ret = INSTALLSTATE_UNKNOWN;
3307 WCHAR *prod = NULL, *feat = NULL;
3308
3309 TRACE( "%s, %s, %lu, %#lx\n", debugstr_a(szProduct), debugstr_a(szFeature), dwInstallMode, dwReserved );
3310
3311 prod = strdupAtoW( szProduct );
3312 if (szProduct && !prod)
3313 goto end;
3314
3315 feat = strdupAtoW( szFeature );
3316 if (szFeature && !feat)
3317 goto end;
3318
3319 ret = MsiUseFeatureExW( prod, feat, dwInstallMode, dwReserved );
3320
3321 end:
3322 free( prod );
3323 free( feat );
3324
3325 return ret;
3326 }
3327
3328 /***********************************************************************
3329 * MsiUseFeatureW [MSI.@]
3330 */
MsiUseFeatureW(LPCWSTR szProduct,LPCWSTR szFeature)3331 INSTALLSTATE WINAPI MsiUseFeatureW( LPCWSTR szProduct, LPCWSTR szFeature )
3332 {
3333 return MsiUseFeatureExW(szProduct, szFeature, 0, 0);
3334 }
3335
3336 /***********************************************************************
3337 * MsiUseFeatureA [MSI.@]
3338 */
MsiUseFeatureA(LPCSTR szProduct,LPCSTR szFeature)3339 INSTALLSTATE WINAPI MsiUseFeatureA( LPCSTR szProduct, LPCSTR szFeature )
3340 {
3341 return MsiUseFeatureExA(szProduct, szFeature, 0, 0);
3342 }
3343
reg_get_multisz(HKEY hkey,const WCHAR * name)3344 static WCHAR *reg_get_multisz( HKEY hkey, const WCHAR *name )
3345 {
3346 WCHAR *ret;
3347 DWORD len, type;
3348 if (RegQueryValueExW( hkey, name, NULL, &type, NULL, &len ) || type != REG_MULTI_SZ) return NULL;
3349 if ((ret = malloc( len ))) RegQueryValueExW( hkey, name, NULL, NULL, (BYTE *)ret, &len );
3350 return ret;
3351 }
3352
reg_get_sz(HKEY hkey,const WCHAR * name)3353 static WCHAR *reg_get_sz( HKEY hkey, const WCHAR *name )
3354 {
3355 WCHAR *ret;
3356 DWORD len, type;
3357 if (RegQueryValueExW( hkey, name, NULL, &type, NULL, &len ) || type != REG_SZ) return NULL;
3358 if ((ret = malloc( len ))) RegQueryValueExW( hkey, name, NULL, NULL, (BYTE *)ret, &len );
3359 return ret;
3360 }
3361
3362 #define BASE85_SIZE 20
3363
3364 /***********************************************************************
3365 * MSI_ProvideQualifiedComponentEx [internal]
3366 */
MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent,LPCWSTR szQualifier,DWORD dwInstallMode,LPCWSTR szProduct,DWORD Unused1,DWORD Unused2,awstring * lpPathBuf,LPDWORD pcchPathBuf)3367 static UINT MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent,
3368 LPCWSTR szQualifier, DWORD dwInstallMode, LPCWSTR szProduct,
3369 DWORD Unused1, DWORD Unused2, awstring *lpPathBuf,
3370 LPDWORD pcchPathBuf)
3371 {
3372 WCHAR product[MAX_FEATURE_CHARS+1], comp[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1];
3373 WCHAR *desc;
3374 HKEY hkey;
3375 DWORD size;
3376 UINT ret;
3377 INSTALLSTATE state;
3378
3379 if (MSIREG_OpenUserComponentsKey( szComponent, &hkey, FALSE )) return ERROR_UNKNOWN_COMPONENT;
3380
3381 desc = reg_get_multisz( hkey, szQualifier );
3382 RegCloseKey(hkey);
3383 if (!desc) return ERROR_INDEX_ABSENT;
3384
3385 /* FIXME: handle multiple descriptors */
3386 ret = MsiDecomposeDescriptorW( desc, product, feature, comp, &size );
3387 free( desc );
3388 if (ret != ERROR_SUCCESS) return ret;
3389
3390 if (!szProduct) szProduct = product;
3391 if (!comp[0])
3392 {
3393 MSIINSTALLCONTEXT ctx;
3394 WCHAR *components;
3395 GUID guid;
3396
3397 /* use the first component of the feature if the descriptor component is empty */
3398 if ((ret = msi_locate_product( szProduct, &ctx ))) return ret;
3399 if ((ret = MSIREG_OpenUserDataFeaturesKey( szProduct, NULL, ctx, &hkey, FALSE )))
3400 {
3401 return ERROR_FILE_NOT_FOUND;
3402 }
3403 components = reg_get_sz( hkey, feature );
3404 RegCloseKey( hkey );
3405 if (!components) return ERROR_FILE_NOT_FOUND;
3406
3407 if (lstrlenW( components ) < BASE85_SIZE || !decode_base85_guid( components, &guid ))
3408 {
3409 free( components );
3410 return ERROR_FILE_NOT_FOUND;
3411 }
3412 free( components );
3413 StringFromGUID2( &guid, comp, ARRAY_SIZE( comp ));
3414 }
3415
3416 state = MSI_GetComponentPath( szProduct, comp, L"S-1-1-0", MSIINSTALLCONTEXT_ALL, lpPathBuf, pcchPathBuf );
3417
3418 if (state == INSTALLSTATE_MOREDATA) return ERROR_MORE_DATA;
3419 if (state != INSTALLSTATE_LOCAL) return ERROR_FILE_NOT_FOUND;
3420 return ERROR_SUCCESS;
3421 }
3422
3423 /***********************************************************************
3424 * MsiProvideQualifiedComponentExW [MSI.@]
3425 */
MsiProvideQualifiedComponentExW(const WCHAR * szComponent,const WCHAR * szQualifier,DWORD dwInstallMode,const WCHAR * szProduct,DWORD Unused1,DWORD Unused2,WCHAR * lpPathBuf,DWORD * pcchPathBuf)3426 UINT WINAPI MsiProvideQualifiedComponentExW( const WCHAR *szComponent, const WCHAR *szQualifier, DWORD dwInstallMode,
3427 const WCHAR *szProduct, DWORD Unused1, DWORD Unused2, WCHAR *lpPathBuf,
3428 DWORD *pcchPathBuf )
3429 {
3430 awstring path;
3431
3432 TRACE( "%s, %s, %lu, %s, %#lx, %#lx, %p, %p\n", debugstr_w(szComponent), debugstr_w(szQualifier), dwInstallMode,
3433 debugstr_w(szProduct), Unused1, Unused2, lpPathBuf, pcchPathBuf );
3434
3435 path.unicode = TRUE;
3436 path.str.w = lpPathBuf;
3437
3438 return MSI_ProvideQualifiedComponentEx( szComponent, szQualifier, dwInstallMode, szProduct, Unused1, Unused2,
3439 &path, pcchPathBuf );
3440 }
3441
3442 /***********************************************************************
3443 * MsiProvideQualifiedComponentExA [MSI.@]
3444 */
MsiProvideQualifiedComponentExA(const char * szComponent,const char * szQualifier,DWORD dwInstallMode,const char * szProduct,DWORD Unused1,DWORD Unused2,char * lpPathBuf,DWORD * pcchPathBuf)3445 UINT WINAPI MsiProvideQualifiedComponentExA( const char *szComponent, const char *szQualifier, DWORD dwInstallMode,
3446 const char *szProduct, DWORD Unused1, DWORD Unused2, char *lpPathBuf,
3447 DWORD *pcchPathBuf )
3448 {
3449 WCHAR *szwComponent, *szwQualifier = NULL, *szwProduct = NULL;
3450 UINT r = ERROR_OUTOFMEMORY;
3451 awstring path;
3452
3453 TRACE( "%s, %s, %lu, %s, %#lx, %#lx, %p, %p\n", debugstr_a(szComponent), debugstr_a(szQualifier), dwInstallMode,
3454 debugstr_a(szProduct), Unused1, Unused2, lpPathBuf, pcchPathBuf );
3455
3456 szwComponent = strdupAtoW( szComponent );
3457 if (szComponent && !szwComponent)
3458 goto end;
3459
3460 szwQualifier = strdupAtoW( szQualifier );
3461 if (szQualifier && !szwQualifier)
3462 goto end;
3463
3464 szwProduct = strdupAtoW( szProduct );
3465 if (szProduct && !szwProduct)
3466 goto end;
3467
3468 path.unicode = FALSE;
3469 path.str.a = lpPathBuf;
3470
3471 r = MSI_ProvideQualifiedComponentEx(szwComponent, szwQualifier,
3472 dwInstallMode, szwProduct, Unused1,
3473 Unused2, &path, pcchPathBuf);
3474 end:
3475 free(szwProduct);
3476 free(szwComponent);
3477 free(szwQualifier);
3478
3479 return r;
3480 }
3481
3482 /***********************************************************************
3483 * MsiProvideQualifiedComponentW [MSI.@]
3484 */
MsiProvideQualifiedComponentW(LPCWSTR szComponent,LPCWSTR szQualifier,DWORD dwInstallMode,LPWSTR lpPathBuf,LPDWORD pcchPathBuf)3485 UINT WINAPI MsiProvideQualifiedComponentW( LPCWSTR szComponent,
3486 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR lpPathBuf,
3487 LPDWORD pcchPathBuf)
3488 {
3489 return MsiProvideQualifiedComponentExW(szComponent, szQualifier,
3490 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
3491 }
3492
3493 /***********************************************************************
3494 * MsiProvideQualifiedComponentA [MSI.@]
3495 */
MsiProvideQualifiedComponentA(LPCSTR szComponent,LPCSTR szQualifier,DWORD dwInstallMode,LPSTR lpPathBuf,LPDWORD pcchPathBuf)3496 UINT WINAPI MsiProvideQualifiedComponentA( LPCSTR szComponent,
3497 LPCSTR szQualifier, DWORD dwInstallMode, LPSTR lpPathBuf,
3498 LPDWORD pcchPathBuf)
3499 {
3500 return MsiProvideQualifiedComponentExA(szComponent, szQualifier,
3501 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
3502 }
3503
3504 /***********************************************************************
3505 * MSI_GetUserInfo [internal]
3506 */
MSI_GetUserInfo(LPCWSTR szProduct,awstring * lpUserNameBuf,LPDWORD pcchUserNameBuf,awstring * lpOrgNameBuf,LPDWORD pcchOrgNameBuf,awstring * lpSerialBuf,LPDWORD pcchSerialBuf)3507 static USERINFOSTATE MSI_GetUserInfo(LPCWSTR szProduct,
3508 awstring *lpUserNameBuf, LPDWORD pcchUserNameBuf,
3509 awstring *lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
3510 awstring *lpSerialBuf, LPDWORD pcchSerialBuf)
3511 {
3512 WCHAR *user, *org, *serial, squashed_pc[SQUASHED_GUID_SIZE];
3513 USERINFOSTATE state;
3514 HKEY hkey, props;
3515 LPCWSTR orgptr;
3516 UINT r;
3517
3518 TRACE("%s %p %p %p %p %p %p\n", debugstr_w(szProduct), lpUserNameBuf,
3519 pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf,
3520 pcchSerialBuf);
3521
3522 if (!szProduct || !squash_guid( szProduct, squashed_pc ))
3523 return USERINFOSTATE_INVALIDARG;
3524
3525 if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
3526 &hkey, FALSE) != ERROR_SUCCESS &&
3527 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3528 &hkey, FALSE) != ERROR_SUCCESS &&
3529 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
3530 &hkey, FALSE) != ERROR_SUCCESS)
3531 {
3532 return USERINFOSTATE_UNKNOWN;
3533 }
3534
3535 if (MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
3536 NULL, &props, FALSE) != ERROR_SUCCESS &&
3537 MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE,
3538 NULL, &props, FALSE) != ERROR_SUCCESS)
3539 {
3540 RegCloseKey(hkey);
3541 return USERINFOSTATE_ABSENT;
3542 }
3543
3544 user = msi_reg_get_val_str(props, INSTALLPROPERTY_REGOWNERW);
3545 org = msi_reg_get_val_str(props, INSTALLPROPERTY_REGCOMPANYW);
3546 serial = msi_reg_get_val_str(props, INSTALLPROPERTY_PRODUCTIDW);
3547 state = USERINFOSTATE_ABSENT;
3548
3549 RegCloseKey(hkey);
3550 RegCloseKey(props);
3551
3552 if (user && serial)
3553 state = USERINFOSTATE_PRESENT;
3554
3555 if (pcchUserNameBuf)
3556 {
3557 if (lpUserNameBuf && !user)
3558 {
3559 (*pcchUserNameBuf)--;
3560 goto done;
3561 }
3562
3563 r = msi_strcpy_to_awstring(user, -1, lpUserNameBuf, pcchUserNameBuf);
3564 if (r == ERROR_MORE_DATA)
3565 {
3566 state = USERINFOSTATE_MOREDATA;
3567 goto done;
3568 }
3569 }
3570
3571 if (pcchOrgNameBuf)
3572 {
3573 orgptr = org;
3574 if (!orgptr) orgptr = L"";
3575
3576 r = msi_strcpy_to_awstring(orgptr, -1, lpOrgNameBuf, pcchOrgNameBuf);
3577 if (r == ERROR_MORE_DATA)
3578 {
3579 state = USERINFOSTATE_MOREDATA;
3580 goto done;
3581 }
3582 }
3583
3584 if (pcchSerialBuf)
3585 {
3586 if (!serial)
3587 {
3588 (*pcchSerialBuf)--;
3589 goto done;
3590 }
3591
3592 r = msi_strcpy_to_awstring(serial, -1, lpSerialBuf, pcchSerialBuf);
3593 if (r == ERROR_MORE_DATA)
3594 state = USERINFOSTATE_MOREDATA;
3595 }
3596
3597 done:
3598 free(user);
3599 free(org);
3600 free(serial);
3601
3602 return state;
3603 }
3604
3605 /***********************************************************************
3606 * MsiGetUserInfoW [MSI.@]
3607 */
MsiGetUserInfoW(LPCWSTR szProduct,LPWSTR lpUserNameBuf,LPDWORD pcchUserNameBuf,LPWSTR lpOrgNameBuf,LPDWORD pcchOrgNameBuf,LPWSTR lpSerialBuf,LPDWORD pcchSerialBuf)3608 USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct,
3609 LPWSTR lpUserNameBuf, LPDWORD pcchUserNameBuf,
3610 LPWSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
3611 LPWSTR lpSerialBuf, LPDWORD pcchSerialBuf)
3612 {
3613 awstring user, org, serial;
3614
3615 if ((lpUserNameBuf && !pcchUserNameBuf) ||
3616 (lpOrgNameBuf && !pcchOrgNameBuf) ||
3617 (lpSerialBuf && !pcchSerialBuf))
3618 return USERINFOSTATE_INVALIDARG;
3619
3620 user.unicode = TRUE;
3621 user.str.w = lpUserNameBuf;
3622 org.unicode = TRUE;
3623 org.str.w = lpOrgNameBuf;
3624 serial.unicode = TRUE;
3625 serial.str.w = lpSerialBuf;
3626
3627 return MSI_GetUserInfo( szProduct, &user, pcchUserNameBuf,
3628 &org, pcchOrgNameBuf,
3629 &serial, pcchSerialBuf );
3630 }
3631
MsiGetUserInfoA(LPCSTR szProduct,LPSTR lpUserNameBuf,LPDWORD pcchUserNameBuf,LPSTR lpOrgNameBuf,LPDWORD pcchOrgNameBuf,LPSTR lpSerialBuf,LPDWORD pcchSerialBuf)3632 USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR szProduct,
3633 LPSTR lpUserNameBuf, LPDWORD pcchUserNameBuf,
3634 LPSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
3635 LPSTR lpSerialBuf, LPDWORD pcchSerialBuf)
3636 {
3637 awstring user, org, serial;
3638 LPWSTR prod;
3639 UINT r;
3640
3641 if ((lpUserNameBuf && !pcchUserNameBuf) ||
3642 (lpOrgNameBuf && !pcchOrgNameBuf) ||
3643 (lpSerialBuf && !pcchSerialBuf))
3644 return USERINFOSTATE_INVALIDARG;
3645
3646 prod = strdupAtoW( szProduct );
3647 if (szProduct && !prod)
3648 return ERROR_OUTOFMEMORY;
3649
3650 user.unicode = FALSE;
3651 user.str.a = lpUserNameBuf;
3652 org.unicode = FALSE;
3653 org.str.a = lpOrgNameBuf;
3654 serial.unicode = FALSE;
3655 serial.str.a = lpSerialBuf;
3656
3657 r = MSI_GetUserInfo( prod, &user, pcchUserNameBuf,
3658 &org, pcchOrgNameBuf,
3659 &serial, pcchSerialBuf );
3660
3661 free( prod );
3662
3663 return r;
3664 }
3665
MsiCollectUserInfoW(LPCWSTR szProduct)3666 UINT WINAPI MsiCollectUserInfoW(LPCWSTR szProduct)
3667 {
3668 MSIHANDLE handle;
3669 UINT rc;
3670 MSIPACKAGE *package;
3671
3672 TRACE("(%s)\n",debugstr_w(szProduct));
3673
3674 rc = MsiOpenProductW(szProduct,&handle);
3675 if (rc != ERROR_SUCCESS)
3676 return ERROR_INVALID_PARAMETER;
3677
3678 /* MsiCollectUserInfo cannot be called from a custom action. */
3679 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
3680 if (!package)
3681 return ERROR_CALL_NOT_IMPLEMENTED;
3682
3683 rc = ACTION_PerformAction(package, L"FirstRun");
3684 msiobj_release( &package->hdr );
3685
3686 MsiCloseHandle(handle);
3687
3688 return rc;
3689 }
3690
MsiCollectUserInfoA(LPCSTR szProduct)3691 UINT WINAPI MsiCollectUserInfoA(LPCSTR szProduct)
3692 {
3693 MSIHANDLE handle;
3694 UINT rc;
3695 MSIPACKAGE *package;
3696
3697 TRACE("(%s)\n",debugstr_a(szProduct));
3698
3699 rc = MsiOpenProductA(szProduct,&handle);
3700 if (rc != ERROR_SUCCESS)
3701 return ERROR_INVALID_PARAMETER;
3702
3703 /* MsiCollectUserInfo cannot be called from a custom action. */
3704 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
3705 if (!package)
3706 return ERROR_CALL_NOT_IMPLEMENTED;
3707
3708 rc = ACTION_PerformAction(package, L"FirstRun");
3709 msiobj_release( &package->hdr );
3710
3711 MsiCloseHandle(handle);
3712
3713 return rc;
3714 }
3715
3716 /***********************************************************************
3717 * MsiConfigureFeatureA [MSI.@]
3718 */
MsiConfigureFeatureA(LPCSTR szProduct,LPCSTR szFeature,INSTALLSTATE eInstallState)3719 UINT WINAPI MsiConfigureFeatureA(LPCSTR szProduct, LPCSTR szFeature, INSTALLSTATE eInstallState)
3720 {
3721 LPWSTR prod, feat = NULL;
3722 UINT r = ERROR_OUTOFMEMORY;
3723
3724 TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature), eInstallState);
3725
3726 prod = strdupAtoW( szProduct );
3727 if (szProduct && !prod)
3728 goto end;
3729
3730 feat = strdupAtoW( szFeature );
3731 if (szFeature && !feat)
3732 goto end;
3733
3734 r = MsiConfigureFeatureW(prod, feat, eInstallState);
3735
3736 end:
3737 free(feat);
3738 free(prod);
3739
3740 return r;
3741 }
3742
3743 /***********************************************************************
3744 * MsiConfigureFeatureW [MSI.@]
3745 */
MsiConfigureFeatureW(LPCWSTR szProduct,LPCWSTR szFeature,INSTALLSTATE eInstallState)3746 UINT WINAPI MsiConfigureFeatureW(LPCWSTR szProduct, LPCWSTR szFeature, INSTALLSTATE eInstallState)
3747 {
3748 MSIPACKAGE *package = NULL;
3749 UINT r;
3750 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH];
3751 DWORD sz;
3752
3753 TRACE("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature), eInstallState);
3754
3755 if (!szProduct || !szFeature)
3756 return ERROR_INVALID_PARAMETER;
3757
3758 switch (eInstallState)
3759 {
3760 case INSTALLSTATE_DEFAULT:
3761 /* FIXME: how do we figure out the default location? */
3762 eInstallState = INSTALLSTATE_LOCAL;
3763 break;
3764 case INSTALLSTATE_LOCAL:
3765 case INSTALLSTATE_SOURCE:
3766 case INSTALLSTATE_ABSENT:
3767 case INSTALLSTATE_ADVERTISED:
3768 break;
3769 default:
3770 return ERROR_INVALID_PARAMETER;
3771 }
3772
3773 r = MSI_OpenProductW( szProduct, &package );
3774 if (r != ERROR_SUCCESS)
3775 return r;
3776
3777 sz = sizeof(sourcepath);
3778 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3779 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
3780
3781 sz = sizeof(filename);
3782 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3783 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
3784
3785 lstrcatW( sourcepath, filename );
3786
3787 MsiSetInternalUI( INSTALLUILEVEL_BASIC, NULL );
3788
3789 r = ACTION_PerformAction(package, L"CostInitialize");
3790 if (r != ERROR_SUCCESS)
3791 goto end;
3792
3793 r = MSI_SetFeatureStateW( package, szFeature, eInstallState);
3794 if (r != ERROR_SUCCESS)
3795 goto end;
3796
3797 r = MSI_InstallPackage( package, sourcepath, NULL );
3798
3799 end:
3800 msiobj_release( &package->hdr );
3801
3802 return r;
3803 }
3804
3805 /***********************************************************************
3806 * MsiCreateAndVerifyInstallerDirectory [MSI.@]
3807 *
3808 * Notes: undocumented
3809 */
MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved)3810 UINT WINAPI MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved)
3811 {
3812 WCHAR path[MAX_PATH];
3813
3814 TRACE( "%#lx\n", dwReserved );
3815
3816 if (dwReserved)
3817 {
3818 FIXME( "dwReserved = %#lx\n", dwReserved );
3819 return ERROR_INVALID_PARAMETER;
3820 }
3821
3822 if (!GetWindowsDirectoryW(path, MAX_PATH))
3823 return ERROR_FUNCTION_FAILED;
3824
3825 lstrcatW(path, L"\\Installer");
3826
3827 if (!CreateDirectoryW(path, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
3828 return ERROR_FUNCTION_FAILED;
3829
3830 return ERROR_SUCCESS;
3831 }
3832
3833 /***********************************************************************
3834 * MsiGetShortcutTargetA [MSI.@]
3835 */
MsiGetShortcutTargetA(LPCSTR szShortcutTarget,LPSTR szProductCode,LPSTR szFeatureId,LPSTR szComponentCode)3836 UINT WINAPI MsiGetShortcutTargetA( LPCSTR szShortcutTarget,
3837 LPSTR szProductCode, LPSTR szFeatureId,
3838 LPSTR szComponentCode )
3839 {
3840 LPWSTR target;
3841 const int len = MAX_FEATURE_CHARS+1;
3842 WCHAR product[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1], component[MAX_FEATURE_CHARS+1];
3843 UINT r;
3844
3845 target = strdupAtoW( szShortcutTarget );
3846 if (szShortcutTarget && !target )
3847 return ERROR_OUTOFMEMORY;
3848 product[0] = 0;
3849 feature[0] = 0;
3850 component[0] = 0;
3851 r = MsiGetShortcutTargetW( target, product, feature, component );
3852 free( target );
3853 if (r == ERROR_SUCCESS)
3854 {
3855 WideCharToMultiByte( CP_ACP, 0, product, -1, szProductCode, len, NULL, NULL );
3856 WideCharToMultiByte( CP_ACP, 0, feature, -1, szFeatureId, len, NULL, NULL );
3857 WideCharToMultiByte( CP_ACP, 0, component, -1, szComponentCode, len, NULL, NULL );
3858 }
3859 return r;
3860 }
3861
3862 /***********************************************************************
3863 * MsiGetShortcutTargetW [MSI.@]
3864 */
MsiGetShortcutTargetW(LPCWSTR szShortcutTarget,LPWSTR szProductCode,LPWSTR szFeatureId,LPWSTR szComponentCode)3865 UINT WINAPI MsiGetShortcutTargetW( LPCWSTR szShortcutTarget,
3866 LPWSTR szProductCode, LPWSTR szFeatureId,
3867 LPWSTR szComponentCode )
3868 {
3869 IShellLinkDataList *dl = NULL;
3870 IPersistFile *pf = NULL;
3871 LPEXP_DARWIN_LINK darwin = NULL;
3872 HRESULT r, init;
3873
3874 TRACE("%s %p %p %p\n", debugstr_w(szShortcutTarget),
3875 szProductCode, szFeatureId, szComponentCode );
3876
3877 init = CoInitialize(NULL);
3878
3879 r = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
3880 &IID_IPersistFile, (LPVOID*) &pf );
3881 if( SUCCEEDED( r ) )
3882 {
3883 r = IPersistFile_Load( pf, szShortcutTarget,
3884 STGM_READ | STGM_SHARE_DENY_WRITE );
3885 if( SUCCEEDED( r ) )
3886 {
3887 r = IPersistFile_QueryInterface( pf, &IID_IShellLinkDataList,
3888 (LPVOID*) &dl );
3889 if( SUCCEEDED( r ) )
3890 {
3891 IShellLinkDataList_CopyDataBlock( dl, EXP_DARWIN_ID_SIG,
3892 (LPVOID) &darwin );
3893 IShellLinkDataList_Release( dl );
3894 }
3895 }
3896 IPersistFile_Release( pf );
3897 }
3898
3899 if (SUCCEEDED(init))
3900 CoUninitialize();
3901
3902 TRACE("darwin = %p\n", darwin);
3903
3904 if (darwin)
3905 {
3906 DWORD sz;
3907 UINT ret;
3908
3909 ret = MsiDecomposeDescriptorW( darwin->szwDarwinID,
3910 szProductCode, szFeatureId, szComponentCode, &sz );
3911 LocalFree( darwin );
3912 return ret;
3913 }
3914
3915 return ERROR_FUNCTION_FAILED;
3916 }
3917
MsiReinstallFeatureW(const WCHAR * szProduct,const WCHAR * szFeature,DWORD dwReinstallMode)3918 UINT WINAPI MsiReinstallFeatureW( const WCHAR *szProduct, const WCHAR *szFeature, DWORD dwReinstallMode )
3919 {
3920 MSIPACKAGE *package;
3921 MSIINSTALLCONTEXT context;
3922 UINT r;
3923 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH], reinstallmode[11];
3924 WCHAR *ptr, *cmdline;
3925 DWORD sz;
3926
3927 TRACE( "%s, %s, %#lx\n", debugstr_w(szProduct), debugstr_w(szFeature), dwReinstallMode );
3928
3929 r = msi_locate_product( szProduct, &context );
3930 if (r != ERROR_SUCCESS)
3931 return r;
3932
3933 ptr = reinstallmode;
3934
3935 if (dwReinstallMode & REINSTALLMODE_FILEMISSING)
3936 *ptr++ = 'p';
3937 if (dwReinstallMode & REINSTALLMODE_FILEOLDERVERSION)
3938 *ptr++ = 'o';
3939 if (dwReinstallMode & REINSTALLMODE_FILEEQUALVERSION)
3940 *ptr++ = 'w';
3941 if (dwReinstallMode & REINSTALLMODE_FILEEXACT)
3942 *ptr++ = 'd';
3943 if (dwReinstallMode & REINSTALLMODE_FILEVERIFY)
3944 *ptr++ = 'c';
3945 if (dwReinstallMode & REINSTALLMODE_FILEREPLACE)
3946 *ptr++ = 'a';
3947 if (dwReinstallMode & REINSTALLMODE_USERDATA)
3948 *ptr++ = 'u';
3949 if (dwReinstallMode & REINSTALLMODE_MACHINEDATA)
3950 *ptr++ = 'm';
3951 if (dwReinstallMode & REINSTALLMODE_SHORTCUT)
3952 *ptr++ = 's';
3953 if (dwReinstallMode & REINSTALLMODE_PACKAGE)
3954 *ptr++ = 'v';
3955 *ptr = 0;
3956
3957 sz = sizeof(sourcepath);
3958 MsiSourceListGetInfoW( szProduct, NULL, context, MSICODE_PRODUCT,
3959 INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz );
3960 sz = sizeof(filename);
3961 MsiSourceListGetInfoW( szProduct, NULL, context, MSICODE_PRODUCT,
3962 INSTALLPROPERTY_PACKAGENAMEW, filename, &sz );
3963 lstrcatW( sourcepath, filename );
3964
3965 if (dwReinstallMode & REINSTALLMODE_PACKAGE)
3966 r = MSI_OpenPackageW( sourcepath, 0, &package );
3967 else
3968 r = MSI_OpenProductW( szProduct, &package );
3969
3970 if (r != ERROR_SUCCESS)
3971 return r;
3972
3973 sz = (lstrlenW( L"%s=%s %s=%s" ) + lstrlenW( L"REINSTALLMODE" ) + lstrlenW( reinstallmode )) * sizeof(WCHAR);
3974 sz += (lstrlenW( L"REINSTALL" ) + lstrlenW( szFeature )) * sizeof(WCHAR);
3975 if (!(cmdline = malloc( sz )))
3976 {
3977 msiobj_release( &package->hdr );
3978 return ERROR_OUTOFMEMORY;
3979 }
3980 swprintf( cmdline, sz / sizeof(WCHAR), L"%s=%s %s=%s", L"REINSTALLMODE", reinstallmode, L"REINSTALL", szFeature );
3981
3982 r = MSI_InstallPackage( package, sourcepath, cmdline );
3983 msiobj_release( &package->hdr );
3984 free( cmdline );
3985
3986 return r;
3987 }
3988
MsiReinstallFeatureA(const char * szProduct,const char * szFeature,DWORD dwReinstallMode)3989 UINT WINAPI MsiReinstallFeatureA( const char *szProduct, const char *szFeature, DWORD dwReinstallMode )
3990 {
3991 WCHAR *wszProduct, *wszFeature;
3992 UINT rc;
3993
3994 TRACE( "%s, %s, %lu\n", debugstr_a(szProduct), debugstr_a(szFeature), dwReinstallMode );
3995
3996 wszProduct = strdupAtoW(szProduct);
3997 wszFeature = strdupAtoW(szFeature);
3998
3999 rc = MsiReinstallFeatureW(wszProduct, wszFeature, dwReinstallMode);
4000
4001 free(wszProduct);
4002 free(wszFeature);
4003 return rc;
4004 }
4005
4006 struct md5_ctx
4007 {
4008 unsigned int i[2];
4009 unsigned int buf[4];
4010 unsigned char in[64];
4011 unsigned char digest[16];
4012 };
4013
4014 extern void WINAPI MD5Init( struct md5_ctx * );
4015 extern void WINAPI MD5Update( struct md5_ctx *, const unsigned char *, unsigned int );
4016 extern void WINAPI MD5Final( struct md5_ctx * );
4017
msi_get_filehash(MSIPACKAGE * package,const WCHAR * path,MSIFILEHASHINFO * hash)4018 UINT msi_get_filehash( MSIPACKAGE *package, const WCHAR *path, MSIFILEHASHINFO *hash )
4019 {
4020 HANDLE handle, mapping;
4021 void *p;
4022 DWORD length;
4023 UINT r = ERROR_FUNCTION_FAILED;
4024
4025 if (package)
4026 handle = msi_create_file( package, path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, OPEN_EXISTING, 0 );
4027 else
4028 handle = CreateFileW( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL );
4029 if (handle == INVALID_HANDLE_VALUE)
4030 {
4031 WARN( "can't open file %lu\n", GetLastError() );
4032 return ERROR_FILE_NOT_FOUND;
4033 }
4034 if ((length = GetFileSize( handle, NULL )))
4035 {
4036 if ((mapping = CreateFileMappingW( handle, NULL, PAGE_READONLY, 0, 0, NULL )))
4037 {
4038 if ((p = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, length )))
4039 {
4040 struct md5_ctx ctx;
4041
4042 MD5Init( &ctx );
4043 MD5Update( &ctx, p, length );
4044 MD5Final( &ctx );
4045 UnmapViewOfFile( p );
4046
4047 memcpy( hash->dwData, ctx.digest, sizeof(hash->dwData) );
4048 r = ERROR_SUCCESS;
4049 }
4050 CloseHandle( mapping );
4051 }
4052 }
4053 else
4054 {
4055 /* Empty file -> set hash to 0 */
4056 memset( hash->dwData, 0, sizeof(hash->dwData) );
4057 r = ERROR_SUCCESS;
4058 }
4059
4060 CloseHandle( handle );
4061 return r;
4062 }
4063
4064 /***********************************************************************
4065 * MsiGetFileHashW [MSI.@]
4066 */
MsiGetFileHashW(const WCHAR * szFilePath,DWORD dwOptions,MSIFILEHASHINFO * pHash)4067 UINT WINAPI MsiGetFileHashW( const WCHAR *szFilePath, DWORD dwOptions, MSIFILEHASHINFO *pHash )
4068 {
4069 TRACE( "%s, %#lx, %p\n", debugstr_w(szFilePath), dwOptions, pHash );
4070
4071 if (!szFilePath)
4072 return ERROR_INVALID_PARAMETER;
4073
4074 if (!*szFilePath)
4075 return ERROR_PATH_NOT_FOUND;
4076
4077 if (dwOptions)
4078 return ERROR_INVALID_PARAMETER;
4079 if (!pHash)
4080 return ERROR_INVALID_PARAMETER;
4081 if (pHash->dwFileHashInfoSize < sizeof *pHash)
4082 return ERROR_INVALID_PARAMETER;
4083
4084 return msi_get_filehash( NULL, szFilePath, pHash );
4085 }
4086
4087 /***********************************************************************
4088 * MsiGetFileHashA [MSI.@]
4089 */
MsiGetFileHashA(const char * szFilePath,DWORD dwOptions,MSIFILEHASHINFO * pHash)4090 UINT WINAPI MsiGetFileHashA( const char *szFilePath, DWORD dwOptions, MSIFILEHASHINFO *pHash )
4091 {
4092 LPWSTR file;
4093 UINT r;
4094
4095 TRACE( "%s, %#lx, %p\n", debugstr_a(szFilePath), dwOptions, pHash );
4096
4097 file = strdupAtoW( szFilePath );
4098 if (szFilePath && !file)
4099 return ERROR_OUTOFMEMORY;
4100
4101 r = MsiGetFileHashW( file, dwOptions, pHash );
4102 free( file );
4103 return r;
4104 }
4105
4106 /***********************************************************************
4107 * MsiAdvertiseScriptW [MSI.@]
4108 */
MsiAdvertiseScriptW(const WCHAR * szScriptFile,DWORD dwFlags,HKEY * phRegData,BOOL fRemoveItems)4109 UINT WINAPI MsiAdvertiseScriptW( const WCHAR *szScriptFile, DWORD dwFlags, HKEY *phRegData, BOOL fRemoveItems )
4110 {
4111 FIXME( "%s, %#lx, %p, %d\n", debugstr_w(szScriptFile), dwFlags, phRegData, fRemoveItems );
4112 return ERROR_CALL_NOT_IMPLEMENTED;
4113 }
4114
4115 /***********************************************************************
4116 * MsiAdvertiseScriptA [MSI.@]
4117 */
MsiAdvertiseScriptA(const char * szScriptFile,DWORD dwFlags,HKEY * phRegData,BOOL fRemoveItems)4118 UINT WINAPI MsiAdvertiseScriptA( const char *szScriptFile, DWORD dwFlags, HKEY *phRegData, BOOL fRemoveItems )
4119 {
4120 FIXME( "%s, %#lx, %p, %d\n", debugstr_a(szScriptFile), dwFlags, phRegData, fRemoveItems );
4121 return ERROR_CALL_NOT_IMPLEMENTED;
4122 }
4123
4124 /***********************************************************************
4125 * MsiIsProductElevatedW [MSI.@]
4126 */
MsiIsProductElevatedW(LPCWSTR szProduct,BOOL * pfElevated)4127 UINT WINAPI MsiIsProductElevatedW( LPCWSTR szProduct, BOOL *pfElevated )
4128 {
4129 FIXME("%s %p - stub\n",
4130 debugstr_w( szProduct ), pfElevated );
4131 *pfElevated = TRUE;
4132 return ERROR_SUCCESS;
4133 }
4134
4135 /***********************************************************************
4136 * MsiIsProductElevatedA [MSI.@]
4137 */
MsiIsProductElevatedA(LPCSTR szProduct,BOOL * pfElevated)4138 UINT WINAPI MsiIsProductElevatedA( LPCSTR szProduct, BOOL *pfElevated )
4139 {
4140 FIXME("%s %p - stub\n",
4141 debugstr_a( szProduct ), pfElevated );
4142 *pfElevated = TRUE;
4143 return ERROR_SUCCESS;
4144 }
4145
4146 /***********************************************************************
4147 * MsiSetExternalUIRecord [MSI.@]
4148 */
MsiSetExternalUIRecord(INSTALLUI_HANDLER_RECORD handler,DWORD filter,void * context,INSTALLUI_HANDLER_RECORD * prev)4149 UINT WINAPI MsiSetExternalUIRecord( INSTALLUI_HANDLER_RECORD handler, DWORD filter, void *context,
4150 INSTALLUI_HANDLER_RECORD *prev )
4151 {
4152 TRACE( "%p, %#lx, %p, %p\n", handler, filter, context, prev );
4153
4154 if (prev)
4155 *prev = gUIHandlerRecord;
4156
4157 gUIHandlerRecord = handler;
4158 gUIFilterRecord = filter;
4159 gUIContextRecord = context;
4160
4161 return ERROR_SUCCESS;
4162 }
4163
4164 /***********************************************************************
4165 * MsiInstallMissingComponentA [MSI.@]
4166 */
MsiInstallMissingComponentA(LPCSTR product,LPCSTR component,INSTALLSTATE state)4167 UINT WINAPI MsiInstallMissingComponentA( LPCSTR product, LPCSTR component, INSTALLSTATE state )
4168 {
4169 UINT r;
4170 WCHAR *productW = NULL, *componentW = NULL;
4171
4172 TRACE("%s, %s, %d\n", debugstr_a(product), debugstr_a(component), state);
4173
4174 if (product && !(productW = strdupAtoW( product )))
4175 return ERROR_OUTOFMEMORY;
4176
4177 if (component && !(componentW = strdupAtoW( component )))
4178 {
4179 free( productW );
4180 return ERROR_OUTOFMEMORY;
4181 }
4182
4183 r = MsiInstallMissingComponentW( productW, componentW, state );
4184 free( productW );
4185 free( componentW );
4186 return r;
4187 }
4188
4189 /***********************************************************************
4190 * MsiInstallMissingComponentW [MSI.@]
4191 */
MsiInstallMissingComponentW(LPCWSTR szProduct,LPCWSTR szComponent,INSTALLSTATE eInstallState)4192 UINT WINAPI MsiInstallMissingComponentW(LPCWSTR szProduct, LPCWSTR szComponent, INSTALLSTATE eInstallState)
4193 {
4194 FIXME("(%s %s %d\n", debugstr_w(szProduct), debugstr_w(szComponent), eInstallState);
4195 return ERROR_SUCCESS;
4196 }
4197
MsiProvideComponentA(const char * product,const char * feature,const char * component,DWORD mode,char * buf,DWORD * buflen)4198 UINT WINAPI MsiProvideComponentA( const char *product, const char *feature, const char *component, DWORD mode,
4199 char *buf, DWORD *buflen )
4200 {
4201 WCHAR *productW = NULL, *componentW = NULL, *featureW = NULL, *bufW = NULL;
4202 UINT r = ERROR_OUTOFMEMORY;
4203 DWORD lenW = 0;
4204 int len;
4205
4206 TRACE( "%s, %s, %s, %#lx, %p, %p\n", debugstr_a(product), debugstr_a(component), debugstr_a(feature), mode,
4207 buf, buflen );
4208
4209 if (product && !(productW = strdupAtoW( product ))) goto done;
4210 if (feature && !(featureW = strdupAtoW( feature ))) goto done;
4211 if (component && !(componentW = strdupAtoW( component ))) goto done;
4212
4213 r = MsiProvideComponentW( productW, featureW, componentW, mode, NULL, &lenW );
4214 if (r != ERROR_SUCCESS)
4215 goto done;
4216
4217 if (!(bufW = malloc( ++lenW * sizeof(WCHAR) )))
4218 {
4219 r = ERROR_OUTOFMEMORY;
4220 goto done;
4221 }
4222
4223 r = MsiProvideComponentW( productW, featureW, componentW, mode, bufW, &lenW );
4224 if (r != ERROR_SUCCESS)
4225 goto done;
4226
4227 len = WideCharToMultiByte( CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL );
4228 if (buf)
4229 {
4230 if (len > *buflen)
4231 r = ERROR_MORE_DATA;
4232 else
4233 WideCharToMultiByte( CP_ACP, 0, bufW, -1, buf, *buflen, NULL, NULL );
4234 }
4235
4236 *buflen = len - 1;
4237
4238 done:
4239 free( productW );
4240 free( featureW );
4241 free( componentW );
4242 free( bufW );
4243 return r;
4244 }
4245
MsiProvideComponentW(const WCHAR * product,const WCHAR * feature,const WCHAR * component,DWORD mode,WCHAR * buf,DWORD * buflen)4246 UINT WINAPI MsiProvideComponentW( const WCHAR *product, const WCHAR *feature, const WCHAR *component, DWORD mode,
4247 WCHAR *buf, DWORD *buflen )
4248 {
4249 INSTALLSTATE state;
4250
4251 TRACE( "%s, %s, %s, %#lx, %p, %p\n", debugstr_w(product), debugstr_w(component), debugstr_w(feature), mode,
4252 buf, buflen);
4253
4254 state = MsiQueryFeatureStateW( product, feature );
4255 TRACE("feature state: %d\n", state);
4256 switch (mode)
4257 {
4258 case INSTALLMODE_NODETECTION:
4259 break;
4260
4261 default:
4262 FIXME( "mode %#lx not implemented\n", mode );
4263 return ERROR_INSTALL_FAILURE;
4264 }
4265
4266 state = MsiGetComponentPathW( product, component, buf, buflen );
4267 TRACE("component state: %d\n", state);
4268 switch (state)
4269 {
4270 case INSTALLSTATE_INVALIDARG:
4271 return ERROR_INVALID_PARAMETER;
4272
4273 case INSTALLSTATE_MOREDATA:
4274 return ERROR_MORE_DATA;
4275
4276 case INSTALLSTATE_ADVERTISED:
4277 case INSTALLSTATE_LOCAL:
4278 case INSTALLSTATE_SOURCE:
4279 MsiUseFeatureW( product, feature );
4280 return ERROR_SUCCESS;
4281
4282 default:
4283 TRACE("MsiGetComponentPathW returned %d\n", state);
4284 return ERROR_INSTALL_FAILURE;
4285 }
4286 }
4287
4288 /***********************************************************************
4289 * MsiBeginTransactionA [MSI.@]
4290 */
MsiBeginTransactionA(const char * name,DWORD attrs,MSIHANDLE * id,HANDLE * event)4291 UINT WINAPI MsiBeginTransactionA( const char *name, DWORD attrs, MSIHANDLE *id, HANDLE *event )
4292 {
4293 WCHAR *nameW;
4294 UINT r;
4295
4296 FIXME( "%s, %#lx, %p, %p\n", debugstr_a(name), attrs, id, event );
4297
4298 nameW = strdupAtoW( name );
4299 if (name && !nameW)
4300 return ERROR_OUTOFMEMORY;
4301
4302 r = MsiBeginTransactionW( nameW, attrs, id, event );
4303 free( nameW );
4304 return r;
4305 }
4306
4307 /***********************************************************************
4308 * MsiBeginTransactionW [MSI.@]
4309 */
MsiBeginTransactionW(const WCHAR * name,DWORD attrs,MSIHANDLE * id,HANDLE * event)4310 UINT WINAPI MsiBeginTransactionW( const WCHAR *name, DWORD attrs, MSIHANDLE *id, HANDLE *event )
4311 {
4312 FIXME( "%s, %#lx, %p, %p\n", debugstr_w(name), attrs, id, event );
4313
4314 *id = (MSIHANDLE)0xdeadbeef;
4315 *event = (HANDLE)0xdeadbeef;
4316
4317 return ERROR_SUCCESS;
4318 }
4319
4320 /***********************************************************************
4321 * MsiJoinTransaction [MSI.@]
4322 */
MsiJoinTransaction(MSIHANDLE handle,DWORD attrs,HANDLE * event)4323 UINT WINAPI MsiJoinTransaction( MSIHANDLE handle, DWORD attrs, HANDLE *event )
4324 {
4325 FIXME( "%lu, %#lx, %p\n", handle, attrs, event );
4326
4327 *event = (HANDLE)0xdeadbeef;
4328 return ERROR_SUCCESS;
4329 }
4330
4331 /***********************************************************************
4332 * MsiEndTransaction [MSI.@]
4333 */
MsiEndTransaction(DWORD state)4334 UINT WINAPI MsiEndTransaction( DWORD state )
4335 {
4336 FIXME( "%#lx\n", state );
4337 return ERROR_SUCCESS;
4338 }
4339
Migrate10CachedPackagesW(void * a,void * b,void * c,DWORD d)4340 UINT WINAPI Migrate10CachedPackagesW( void *a, void *b, void *c, DWORD d )
4341 {
4342 FIXME( "%p, %p, %p, %#lx\n", a, b, c, d );
4343 return ERROR_SUCCESS;
4344 }
4345
4346 /***********************************************************************
4347 * MsiRemovePatchesA [MSI.@]
4348 */
MsiRemovePatchesA(LPCSTR patchlist,LPCSTR product,INSTALLTYPE type,LPCSTR propertylist)4349 UINT WINAPI MsiRemovePatchesA(LPCSTR patchlist, LPCSTR product, INSTALLTYPE type, LPCSTR propertylist)
4350 {
4351 FIXME("(%s %s %d %s\n", debugstr_a(patchlist), debugstr_a(product), type, debugstr_a(propertylist));
4352 return ERROR_SUCCESS;
4353 }
4354
4355 /***********************************************************************
4356 * MsiRemovePatchesW [MSI.@]
4357 */
MsiRemovePatchesW(LPCWSTR patchlist,LPCWSTR product,INSTALLTYPE type,LPCWSTR propertylist)4358 UINT WINAPI MsiRemovePatchesW(LPCWSTR patchlist, LPCWSTR product, INSTALLTYPE type, LPCWSTR propertylist)
4359 {
4360 FIXME("(%s %s %d %s\n", debugstr_w(patchlist), debugstr_w(product), type, debugstr_w(propertylist));
4361 return ERROR_SUCCESS;
4362 }
4363