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