sync msi to wine 1.1.31
[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 <stdarg.h>
22
23 #define COBJMACROS
24 #define NONAMELESSUNION
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "winnls.h"
30 #include "shlwapi.h"
31 #include "wine/debug.h"
32 #include "msi.h"
33 #include "msidefs.h"
34 #include "msiquery.h"
35 #include "msipriv.h"
36 #include "wincrypt.h"
37 #include "winver.h"
38 #include "winuser.h"
39 #include "shlobj.h"
40 #include "shobjidl.h"
41 #include "objidl.h"
42 #include "wine/unicode.h"
43
44 WINE_DEFAULT_DEBUG_CHANNEL(msi);
45
46 static const WCHAR installerW[] = {'\\','I','n','s','t','a','l','l','e','r',0};
47
48 static UINT msi_locate_product(LPCWSTR szProduct, MSIINSTALLCONTEXT *context)
49 {
50 HKEY hkey = NULL;
51
52 *context = MSIINSTALLCONTEXT_NONE;
53
54 if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
55 &hkey, FALSE) == ERROR_SUCCESS)
56 *context = MSIINSTALLCONTEXT_USERMANAGED;
57 else if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
58 &hkey, FALSE) == ERROR_SUCCESS)
59 *context = MSIINSTALLCONTEXT_MACHINE;
60 else if (MSIREG_OpenProductKey(szProduct, NULL,
61 MSIINSTALLCONTEXT_USERUNMANAGED,
62 &hkey, FALSE) == ERROR_SUCCESS)
63 *context = MSIINSTALLCONTEXT_USERUNMANAGED;
64
65 RegCloseKey(hkey);
66
67 if (*context == MSIINSTALLCONTEXT_NONE)
68 return ERROR_UNKNOWN_PRODUCT;
69
70 return ERROR_SUCCESS;
71 }
72
73 UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct)
74 {
75 UINT r;
76 LPWSTR szwProd = NULL;
77
78 TRACE("%s %p\n",debugstr_a(szProduct), phProduct);
79
80 if( szProduct )
81 {
82 szwProd = strdupAtoW( szProduct );
83 if( !szwProd )
84 return ERROR_OUTOFMEMORY;
85 }
86
87 r = MsiOpenProductW( szwProd, phProduct );
88
89 msi_free( szwProd );
90
91 return r;
92 }
93
94 static UINT MSI_OpenProductW(LPCWSTR szProduct, MSIPACKAGE **package)
95 {
96 UINT r;
97 HKEY props;
98 LPWSTR path;
99 MSIINSTALLCONTEXT context;
100
101 static const WCHAR managed[] = {
102 'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0};
103 static const WCHAR local[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0};
104
105 TRACE("%s %p\n", debugstr_w(szProduct), package);
106
107 r = msi_locate_product(szProduct, &context);
108 if (r != ERROR_SUCCESS)
109 return r;
110
111 r = MSIREG_OpenInstallProps(szProduct, context, NULL, &props, FALSE);
112 if (r != ERROR_SUCCESS)
113 return ERROR_UNKNOWN_PRODUCT;
114
115 if (context == MSIINSTALLCONTEXT_USERMANAGED)
116 path = msi_reg_get_val_str(props, managed);
117 else
118 path = msi_reg_get_val_str(props, local);
119
120 r = ERROR_UNKNOWN_PRODUCT;
121
122 if (!path || GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES)
123 goto done;
124
125 if (PathIsRelativeW(path))
126 {
127 r = ERROR_INSTALL_PACKAGE_OPEN_FAILED;
128 goto done;
129 }
130
131 r = MSI_OpenPackageW(path, package);
132
133 done:
134 RegCloseKey(props);
135 msi_free(path);
136 return r;
137 }
138
139 UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct)
140 {
141 MSIPACKAGE *package = NULL;
142 WCHAR squished_pc[GUID_SIZE];
143 UINT r;
144
145 if (!szProduct || !squash_guid(szProduct, squished_pc))
146 return ERROR_INVALID_PARAMETER;
147
148 if (!phProduct)
149 return ERROR_INVALID_PARAMETER;
150
151 r = MSI_OpenProductW(szProduct, &package);
152 if (r != ERROR_SUCCESS)
153 return r;
154
155 *phProduct = alloc_msihandle(&package->hdr);
156 if (!*phProduct)
157 r = ERROR_NOT_ENOUGH_MEMORY;
158
159 msiobj_release(&package->hdr);
160 return r;
161 }
162
163 UINT WINAPI MsiAdvertiseProductA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
164 LPCSTR szTransforms, LANGID lgidLanguage)
165 {
166 FIXME("%s %s %s %08x\n",debugstr_a(szPackagePath),
167 debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage);
168 return ERROR_CALL_NOT_IMPLEMENTED;
169 }
170
171 UINT WINAPI MsiAdvertiseProductW(LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
172 LPCWSTR szTransforms, LANGID lgidLanguage)
173 {
174 FIXME("%s %s %s %08x\n",debugstr_w(szPackagePath),
175 debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage);
176 return ERROR_CALL_NOT_IMPLEMENTED;
177 }
178
179 UINT WINAPI MsiAdvertiseProductExA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
180 LPCSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
181 {
182 FIXME("%s %s %s %08x %08x %08x\n", debugstr_a(szPackagePath),
183 debugstr_a(szScriptfilePath), debugstr_a(szTransforms),
184 lgidLanguage, dwPlatform, dwOptions);
185 return ERROR_CALL_NOT_IMPLEMENTED;
186 }
187
188 UINT WINAPI MsiAdvertiseProductExW( LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
189 LPCWSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
190 {
191 FIXME("%s %s %s %08x %08x %08x\n", debugstr_w(szPackagePath),
192 debugstr_w(szScriptfilePath), debugstr_w(szTransforms),
193 lgidLanguage, dwPlatform, dwOptions);
194 return ERROR_CALL_NOT_IMPLEMENTED;
195 }
196
197 UINT WINAPI MsiInstallProductA(LPCSTR szPackagePath, LPCSTR szCommandLine)
198 {
199 LPWSTR szwPath = NULL, szwCommand = NULL;
200 UINT r = ERROR_OUTOFMEMORY;
201
202 TRACE("%s %s\n",debugstr_a(szPackagePath), debugstr_a(szCommandLine));
203
204 if( szPackagePath )
205 {
206 szwPath = strdupAtoW( szPackagePath );
207 if( !szwPath )
208 goto end;
209 }
210
211 if( szCommandLine )
212 {
213 szwCommand = strdupAtoW( szCommandLine );
214 if( !szwCommand )
215 goto end;
216 }
217
218 r = MsiInstallProductW( szwPath, szwCommand );
219
220 end:
221 msi_free( szwPath );
222 msi_free( szwCommand );
223
224 return r;
225 }
226
227 UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
228 {
229 MSIPACKAGE *package = NULL;
230 UINT r;
231
232 TRACE("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine));
233
234 if (!szPackagePath)
235 return ERROR_INVALID_PARAMETER;
236
237 if (!*szPackagePath)
238 return ERROR_PATH_NOT_FOUND;
239
240 r = MSI_OpenPackageW( szPackagePath, &package );
241 if (r == ERROR_SUCCESS)
242 {
243 r = MSI_InstallPackage( package, szPackagePath, szCommandLine );
244 msiobj_release( &package->hdr );
245 }
246
247 return r;
248 }
249
250 UINT WINAPI MsiReinstallProductA(LPCSTR szProduct, DWORD dwReinstallMode)
251 {
252 LPWSTR wszProduct;
253 UINT rc;
254
255 TRACE("%s %08x\n", debugstr_a(szProduct), dwReinstallMode);
256
257 wszProduct = strdupAtoW(szProduct);
258
259 rc = MsiReinstallProductW(wszProduct, dwReinstallMode);
260
261 msi_free(wszProduct);
262 return rc;
263 }
264
265 UINT WINAPI MsiReinstallProductW(LPCWSTR szProduct, DWORD dwReinstallMode)
266 {
267 static const WCHAR szAll[] = {'A','L','L',0};
268
269 TRACE("%s %08x\n", debugstr_w(szProduct), dwReinstallMode);
270
271 return MsiReinstallFeatureW(szProduct, szAll, dwReinstallMode);
272 }
273
274 UINT WINAPI MsiApplyPatchA(LPCSTR szPatchPackage, LPCSTR szInstallPackage,
275 INSTALLTYPE eInstallType, LPCSTR szCommandLine)
276 {
277 LPWSTR patch_package = NULL;
278 LPWSTR install_package = NULL;
279 LPWSTR command_line = NULL;
280 UINT r = ERROR_OUTOFMEMORY;
281
282 TRACE("%s %s %d %s\n", debugstr_a(szPatchPackage), debugstr_a(szInstallPackage),
283 eInstallType, debugstr_a(szCommandLine));
284
285 if (szPatchPackage && !(patch_package = strdupAtoW(szPatchPackage)))
286 goto done;
287
288 if (szInstallPackage && !(install_package = strdupAtoW(szInstallPackage)))
289 goto done;
290
291 if (szCommandLine && !(command_line = strdupAtoW(szCommandLine)))
292 goto done;
293
294 r = MsiApplyPatchW(patch_package, install_package, eInstallType, command_line);
295
296 done:
297 msi_free(patch_package);
298 msi_free(install_package);
299 msi_free(command_line);
300
301 return r;
302 }
303
304 static UINT MSI_ApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szProductCode, LPCWSTR szCommandLine)
305 {
306 MSIHANDLE patch = 0, info = 0;
307 UINT r = ERROR_SUCCESS, type;
308 DWORD size = 0;
309 LPCWSTR cmd_ptr = szCommandLine;
310 LPCWSTR product_code = szProductCode;
311 LPWSTR beg, end;
312 LPWSTR cmd = NULL, codes = NULL;
313
314 static const WCHAR space[] = {' ',0};
315 static const WCHAR patcheq[] = {'P','A','T','C','H','=',0};
316 static WCHAR empty[] = {0};
317
318 if (!szPatchPackage || !szPatchPackage[0])
319 return ERROR_INVALID_PARAMETER;
320
321 if (!szProductCode)
322 {
323 r = MsiOpenDatabaseW(szPatchPackage, MSIDBOPEN_READONLY, &patch);
324 if (r != ERROR_SUCCESS)
325 return r;
326
327 r = MsiGetSummaryInformationW(patch, NULL, 0, &info);
328 if (r != ERROR_SUCCESS)
329 goto done;
330
331 r = MsiSummaryInfoGetPropertyW(info, PID_TEMPLATE, &type, NULL, NULL, empty, &size);
332 if (r != ERROR_MORE_DATA || !size || type != VT_LPSTR)
333 {
334 ERR("Failed to read product codes from patch\n");
335 goto done;
336 }
337
338 codes = msi_alloc(++size * sizeof(WCHAR));
339 if (!codes)
340 {
341 r = ERROR_OUTOFMEMORY;
342 goto done;
343 }
344
345 r = MsiSummaryInfoGetPropertyW(info, PID_TEMPLATE, &type, NULL, NULL, codes, &size);
346 if (r != ERROR_SUCCESS)
347 goto done;
348
349 product_code = codes;
350 }
351
352 if (!szCommandLine)
353 cmd_ptr = empty;
354
355 size = lstrlenW(cmd_ptr) + lstrlenW(patcheq) + lstrlenW(szPatchPackage) + 1;
356 cmd = msi_alloc(size * sizeof(WCHAR));
357 if (!cmd)
358 {
359 r = ERROR_OUTOFMEMORY;
360 goto done;
361 }
362
363 lstrcpyW(cmd, cmd_ptr);
364 if (szCommandLine) lstrcatW(cmd, space);
365 lstrcatW(cmd, patcheq);
366 lstrcatW(cmd, szPatchPackage);
367
368 beg = codes;
369 while ((end = strchrW(beg, '}')))
370 {
371 *(end + 1) = '\0';
372
373 r = MsiConfigureProductExW(beg, INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd);
374 if (r != ERROR_SUCCESS)
375 goto done;
376
377 beg = end + 2;
378 }
379
380 done:
381 msi_free(cmd);
382 msi_free(codes);
383
384 MsiCloseHandle(info);
385 MsiCloseHandle(patch);
386
387 return r;
388 }
389
390 UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage,
391 INSTALLTYPE eInstallType, LPCWSTR szCommandLine)
392 {
393 TRACE("%s %s %d %s\n", debugstr_w(szPatchPackage), debugstr_w(szInstallPackage),
394 eInstallType, debugstr_w(szCommandLine));
395
396 if (szInstallPackage || eInstallType == INSTALLTYPE_NETWORK_IMAGE ||
397 eInstallType == INSTALLTYPE_SINGLE_INSTANCE)
398 {
399 FIXME("Only reading target products from patch\n");
400 return ERROR_CALL_NOT_IMPLEMENTED;
401 }
402
403 return MSI_ApplyPatchW(szPatchPackage, NULL, szCommandLine);
404 }
405
406 UINT WINAPI MsiApplyMultiplePatchesA(LPCSTR szPatchPackages,
407 LPCSTR szProductCode, LPCSTR szPropertiesList)
408 {
409 LPWSTR patch_packages = NULL;
410 LPWSTR product_code = NULL;
411 LPWSTR properties_list = NULL;
412 UINT r = ERROR_OUTOFMEMORY;
413
414 TRACE("%s %s %s\n", debugstr_a(szPatchPackages), debugstr_a(szProductCode),
415 debugstr_a(szPropertiesList));
416
417 if (!szPatchPackages || !szPatchPackages[0])
418 return ERROR_INVALID_PARAMETER;
419
420 if (!(patch_packages = strdupAtoW(szPatchPackages)))
421 return ERROR_OUTOFMEMORY;
422
423 if (szProductCode && !(product_code = strdupAtoW(szProductCode)))
424 goto done;
425
426 if (szPropertiesList && !(properties_list = strdupAtoW(szPropertiesList)))
427 goto done;
428
429 r = MsiApplyMultiplePatchesW(patch_packages, product_code, properties_list);
430
431 done:
432 msi_free(patch_packages);
433 msi_free(product_code);
434 msi_free(properties_list);
435
436 return r;
437 }
438
439 UINT WINAPI MsiApplyMultiplePatchesW(LPCWSTR szPatchPackages,
440 LPCWSTR szProductCode, LPCWSTR szPropertiesList)
441 {
442 UINT r = ERROR_SUCCESS;
443 LPCWSTR beg, end;
444
445 TRACE("%s %s %s\n", debugstr_w(szPatchPackages), debugstr_w(szProductCode),
446 debugstr_w(szPropertiesList));
447
448 if (!szPatchPackages || !szPatchPackages[0])
449 return ERROR_INVALID_PARAMETER;
450
451 beg = end = szPatchPackages;
452 while (*beg)
453 {
454 DWORD len;
455 LPWSTR patch;
456
457 while (*beg == ' ') beg++;
458 while (*end && *end != ';') end++;
459
460 len = end - beg;
461 while (len && beg[len - 1] == ' ') len--;
462
463 if (!len) return ERROR_INVALID_NAME;
464
465 patch = msi_alloc((len + 1) * sizeof(WCHAR));
466 if (!patch)
467 return ERROR_OUTOFMEMORY;
468
469 memcpy(patch, beg, len * sizeof(WCHAR));
470 patch[len] = '\0';
471
472 r = MSI_ApplyPatchW(patch, szProductCode, szPropertiesList);
473 msi_free(patch);
474
475 if (r != ERROR_SUCCESS)
476 break;
477
478 beg = ++end;
479 }
480 return r;
481 }
482
483 UINT WINAPI MsiDetermineApplicablePatchesA(LPCSTR szProductPackagePath,
484 DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOA pPatchInfo)
485 {
486 FIXME("(%s, %d, %p): stub!\n", debugstr_a(szProductPackagePath),
487 cPatchInfo, pPatchInfo);
488
489 return ERROR_CALL_NOT_IMPLEMENTED;
490 }
491
492 static UINT MSI_ApplicablePatchW( MSIPACKAGE *package, LPCWSTR patch )
493 {
494 MSISUMMARYINFO *si;
495 MSIDATABASE *patch_db;
496 UINT r = ERROR_SUCCESS;
497
498 r = MSI_OpenDatabaseW( patch, MSIDBOPEN_READONLY, &patch_db );
499 if (r != ERROR_SUCCESS)
500 {
501 WARN("failed to open patch file %s\n", debugstr_w(patch));
502 return r;
503 }
504
505 si = MSI_GetSummaryInformationW( patch_db->storage, 0 );
506 if (!si)
507 {
508 r = ERROR_FUNCTION_FAILED;
509 goto done;
510 }
511
512 r = msi_check_patch_applicable( package, si );
513 if (r != ERROR_SUCCESS)
514 TRACE("patch not applicable\n");
515
516 done:
517 msiobj_release( &patch_db->hdr );
518 msiobj_release( &si->hdr );
519 return r;
520 }
521
522 UINT WINAPI MsiDetermineApplicablePatchesW(LPCWSTR szProductPackagePath,
523 DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOW pPatchInfo)
524 {
525 UINT i, r, ret = ERROR_FUNCTION_FAILED;
526 MSIPACKAGE *package;
527
528 TRACE("(%s, %d, %p)\n", debugstr_w(szProductPackagePath), cPatchInfo, pPatchInfo);
529
530 r = MSI_OpenPackageW( szProductPackagePath, &package );
531 if (r != ERROR_SUCCESS)
532 {
533 ERR("failed to open package %u\n", r);
534 return r;
535 }
536
537 for (i = 0; i < cPatchInfo; i++)
538 {
539 switch (pPatchInfo[i].ePatchDataType)
540 {
541 case MSIPATCH_DATATYPE_PATCHFILE:
542 {
543 FIXME("patch ordering not supported\n");
544 r = MSI_ApplicablePatchW( package, pPatchInfo[i].szPatchData );
545 if (r != ERROR_SUCCESS)
546 {
547 pPatchInfo[i].dwOrder = ~0u;
548 pPatchInfo[i].uStatus = ERROR_PATCH_TARGET_NOT_FOUND;
549 }
550 else
551 {
552 pPatchInfo[i].dwOrder = i;
553 pPatchInfo[i].uStatus = ret = ERROR_SUCCESS;
554 }
555 break;
556 }
557 default:
558 {
559 FIXME("patch data type %u not supported\n", pPatchInfo[i].ePatchDataType);
560 pPatchInfo[i].dwOrder = ~0u;
561 pPatchInfo[i].uStatus = ERROR_PATCH_TARGET_NOT_FOUND;
562 break;
563 }
564 }
565
566 TRACE(" szPatchData: %s\n", debugstr_w(pPatchInfo[i].szPatchData));
567 TRACE("ePatchDataType: %u\n", pPatchInfo[i].ePatchDataType);
568 TRACE(" dwOrder: %u\n", pPatchInfo[i].dwOrder);
569 TRACE(" uStatus: %u\n", pPatchInfo[i].uStatus);
570 }
571 return ret;
572 }
573
574 UINT WINAPI MsiDeterminePatchSequenceA(LPCSTR szProductCode, LPCSTR szUserSid,
575 MSIINSTALLCONTEXT dwContext, DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOA pPatchInfo)
576 {
577 FIXME("(%s, %s, %d, %d, %p): stub!\n", debugstr_a(szProductCode),
578 debugstr_a(szUserSid), dwContext, cPatchInfo, pPatchInfo);
579
580 return ERROR_CALL_NOT_IMPLEMENTED;
581 }
582
583 UINT WINAPI MsiDeterminePatchSequenceW(LPCWSTR szProductCode, LPCWSTR szUserSid,
584 MSIINSTALLCONTEXT dwContext, DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOW pPatchInfo)
585 {
586 FIXME("(%s, %s, %d, %d, %p): stub!\n", debugstr_w(szProductCode),
587 debugstr_w(szUserSid), dwContext, cPatchInfo, pPatchInfo);
588
589 return ERROR_CALL_NOT_IMPLEMENTED;
590 }
591
592 static UINT msi_open_package(LPCWSTR product, MSIINSTALLCONTEXT context,
593 MSIPACKAGE **package)
594 {
595 UINT r;
596 DWORD sz;
597 HKEY props;
598 LPWSTR localpack;
599 WCHAR sourcepath[MAX_PATH];
600 WCHAR filename[MAX_PATH];
601
602 static const WCHAR szLocalPackage[] = {
603 'L','o','c','a','l','P','a','c','k','a','g','e',0};
604
605
606 r = MSIREG_OpenInstallProps(product, context, NULL, &props, FALSE);
607 if (r != ERROR_SUCCESS)
608 return ERROR_BAD_CONFIGURATION;
609
610 localpack = msi_reg_get_val_str(props, szLocalPackage);
611 if (localpack)
612 {
613 lstrcpyW(sourcepath, localpack);
614 msi_free(localpack);
615 }
616
617 if (!localpack || GetFileAttributesW(sourcepath) == INVALID_FILE_ATTRIBUTES)
618 {
619 sz = sizeof(sourcepath);
620 MsiSourceListGetInfoW(product, NULL, context, MSICODE_PRODUCT,
621 INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
622
623 sz = sizeof(filename);
624 MsiSourceListGetInfoW(product, NULL, context, MSICODE_PRODUCT,
625 INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
626
627 lstrcatW(sourcepath, filename);
628 }
629
630 if (GetFileAttributesW(sourcepath) == INVALID_FILE_ATTRIBUTES)
631 return ERROR_INSTALL_SOURCE_ABSENT;
632
633 return MSI_OpenPackageW(sourcepath, package);
634 }
635
636 UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
637 INSTALLSTATE eInstallState, LPCWSTR szCommandLine)
638 {
639 MSIPACKAGE* package = NULL;
640 MSIINSTALLCONTEXT context;
641 UINT r;
642 DWORD sz;
643 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH];
644 LPWSTR commandline;
645
646 static const WCHAR szInstalled[] = {
647 ' ','I','n','s','t','a','l','l','e','d','=','1',0};
648 static const WCHAR szRemoveAll[] = {
649 ' ','R','E','M','O','V','E','=','A','L','L',0};
650 static const WCHAR szMachine[] = {
651 ' ','A','L','L','U','S','E','R','S','=','1',0};
652
653 TRACE("%s %d %d %s\n",debugstr_w(szProduct), iInstallLevel, eInstallState,
654 debugstr_w(szCommandLine));
655
656 if (!szProduct || lstrlenW(szProduct) != GUID_SIZE - 1)
657 return ERROR_INVALID_PARAMETER;
658
659 if (eInstallState == INSTALLSTATE_ADVERTISED ||
660 eInstallState == INSTALLSTATE_SOURCE)
661 {
662 FIXME("State %d not implemented\n", eInstallState);
663 return ERROR_CALL_NOT_IMPLEMENTED;
664 }
665
666 r = msi_locate_product(szProduct, &context);
667 if (r != ERROR_SUCCESS)
668 return r;
669
670 r = msi_open_package(szProduct, context, &package);
671 if (r != ERROR_SUCCESS)
672 return r;
673
674 sz = lstrlenW(szInstalled) + 1;
675
676 if (szCommandLine)
677 sz += lstrlenW(szCommandLine);
678
679 if (eInstallState == INSTALLSTATE_ABSENT)
680 sz += lstrlenW(szRemoveAll);
681
682 if (context == MSIINSTALLCONTEXT_MACHINE)
683 sz += lstrlenW(szMachine);
684
685 commandline = msi_alloc(sz * sizeof(WCHAR));
686 if (!commandline)
687 {
688 r = ERROR_OUTOFMEMORY;
689 goto end;
690 }
691
692 commandline[0] = 0;
693 if (szCommandLine)
694 lstrcpyW(commandline,szCommandLine);
695
696 if (eInstallState == INSTALLSTATE_ABSENT)
697 lstrcatW(commandline, szRemoveAll);
698
699 if (context == MSIINSTALLCONTEXT_MACHINE)
700 lstrcatW(commandline, szMachine);
701
702 sz = sizeof(sourcepath);
703 MsiSourceListGetInfoW(szProduct, NULL, context, MSICODE_PRODUCT,
704 INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
705
706 sz = sizeof(filename);
707 MsiSourceListGetInfoW(szProduct, NULL, context, MSICODE_PRODUCT,
708 INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
709
710 strcatW(sourcepath, filename);
711
712 r = MSI_InstallPackage( package, sourcepath, commandline );
713
714 msi_free(commandline);
715
716 end:
717 msiobj_release( &package->hdr );
718
719 return r;
720 }
721
722 UINT WINAPI MsiConfigureProductExA(LPCSTR szProduct, int iInstallLevel,
723 INSTALLSTATE eInstallState, LPCSTR szCommandLine)
724 {
725 LPWSTR szwProduct = NULL;
726 LPWSTR szwCommandLine = NULL;
727 UINT r = ERROR_OUTOFMEMORY;
728
729 if( szProduct )
730 {
731 szwProduct = strdupAtoW( szProduct );
732 if( !szwProduct )
733 goto end;
734 }
735
736 if( szCommandLine)
737 {
738 szwCommandLine = strdupAtoW( szCommandLine );
739 if( !szwCommandLine)
740 goto end;
741 }
742
743 r = MsiConfigureProductExW( szwProduct, iInstallLevel, eInstallState,
744 szwCommandLine );
745 end:
746 msi_free( szwProduct );
747 msi_free( szwCommandLine);
748
749 return r;
750 }
751
752 UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel,
753 INSTALLSTATE eInstallState)
754 {
755 LPWSTR szwProduct = NULL;
756 UINT r;
757
758 TRACE("%s %d %d\n",debugstr_a(szProduct), iInstallLevel, eInstallState);
759
760 if( szProduct )
761 {
762 szwProduct = strdupAtoW( szProduct );
763 if( !szwProduct )
764 return ERROR_OUTOFMEMORY;
765 }
766
767 r = MsiConfigureProductW( szwProduct, iInstallLevel, eInstallState );
768 msi_free( szwProduct );
769
770 return r;
771 }
772
773 UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel,
774 INSTALLSTATE eInstallState)
775 {
776 return MsiConfigureProductExW(szProduct, iInstallLevel, eInstallState, NULL);
777 }
778
779 UINT WINAPI MsiGetProductCodeA(LPCSTR szComponent, LPSTR szBuffer)
780 {
781 LPWSTR szwComponent = NULL;
782 UINT r;
783 WCHAR szwBuffer[GUID_SIZE];
784
785 TRACE("%s %s\n",debugstr_a(szComponent), debugstr_a(szBuffer));
786
787 if( szComponent )
788 {
789 szwComponent = strdupAtoW( szComponent );
790 if( !szwComponent )
791 return ERROR_OUTOFMEMORY;
792 }
793
794 *szwBuffer = '\0';
795 r = MsiGetProductCodeW( szwComponent, szwBuffer );
796
797 if(*szwBuffer)
798 WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, GUID_SIZE, NULL, NULL);
799
800 msi_free( szwComponent );
801
802 return r;
803 }
804
805 UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer)
806 {
807 UINT rc, index;
808 HKEY compkey, prodkey;
809 WCHAR squished_comp[GUID_SIZE];
810 WCHAR squished_prod[GUID_SIZE];
811 DWORD sz = GUID_SIZE;
812
813 TRACE("%s %p\n", debugstr_w(szComponent), szBuffer);
814
815 if (!szComponent || !*szComponent)
816 return ERROR_INVALID_PARAMETER;
817
818 if (!squash_guid(szComponent, squished_comp))
819 return ERROR_INVALID_PARAMETER;
820
821 if (MSIREG_OpenUserDataComponentKey(szComponent, NULL, &compkey, FALSE) != ERROR_SUCCESS &&
822 MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &compkey, FALSE) != ERROR_SUCCESS)
823 {
824 return ERROR_UNKNOWN_COMPONENT;
825 }
826
827 rc = RegEnumValueW(compkey, 0, squished_prod, &sz, NULL, NULL, NULL, NULL);
828 if (rc != ERROR_SUCCESS)
829 {
830 RegCloseKey(compkey);
831 return ERROR_UNKNOWN_COMPONENT;
832 }
833
834 /* check simple case, only one product */
835 rc = RegEnumValueW(compkey, 1, squished_prod, &sz, NULL, NULL, NULL, NULL);
836 if (rc == ERROR_NO_MORE_ITEMS)
837 {
838 rc = ERROR_SUCCESS;
839 goto done;
840 }
841
842 index = 0;
843 while ((rc = RegEnumValueW(compkey, index, squished_prod, &sz,
844 NULL, NULL, NULL, NULL)) != ERROR_NO_MORE_ITEMS)
845 {
846 index++;
847 sz = GUID_SIZE;
848 unsquash_guid(squished_prod, szBuffer);
849
850 if (MSIREG_OpenProductKey(szBuffer, NULL,
851 MSIINSTALLCONTEXT_USERMANAGED,
852 &prodkey, FALSE) == ERROR_SUCCESS ||
853 MSIREG_OpenProductKey(szBuffer, NULL,
854 MSIINSTALLCONTEXT_USERUNMANAGED,
855 &prodkey, FALSE) == ERROR_SUCCESS ||
856 MSIREG_OpenProductKey(szBuffer, NULL,
857 MSIINSTALLCONTEXT_MACHINE,
858 &prodkey, FALSE) == ERROR_SUCCESS)
859 {
860 RegCloseKey(prodkey);
861 rc = ERROR_SUCCESS;
862 goto done;
863 }
864 }
865
866 rc = ERROR_INSTALL_FAILURE;
867
868 done:
869 RegCloseKey(compkey);
870 unsquash_guid(squished_prod, szBuffer);
871 return rc;
872 }
873
874 static LPWSTR msi_reg_get_value(HKEY hkey, LPCWSTR name, DWORD *type)
875 {
876 DWORD dval;
877 LONG res;
878 WCHAR temp[20];
879
880 static const WCHAR format[] = {'%','d',0};
881
882 res = RegQueryValueExW(hkey, name, NULL, type, NULL, NULL);
883 if (res != ERROR_SUCCESS)
884 return NULL;
885
886 if (*type == REG_SZ)
887 return msi_reg_get_val_str(hkey, name);
888
889 if (!msi_reg_get_val_dword(hkey, name, &dval))
890 return NULL;
891
892 sprintfW(temp, format, dval);
893 return strdupW(temp);
894 }
895
896 static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
897 awstring *szValue, LPDWORD pcchValueBuf)
898 {
899 MSIINSTALLCONTEXT context = MSIINSTALLCONTEXT_USERUNMANAGED;
900 UINT r = ERROR_UNKNOWN_PROPERTY;
901 HKEY prodkey, userdata, source;
902 LPWSTR val = NULL;
903 WCHAR squished_pc[GUID_SIZE];
904 WCHAR packagecode[GUID_SIZE];
905 BOOL badconfig = FALSE;
906 LONG res;
907 DWORD save, type = REG_NONE;
908
909 static WCHAR empty[] = {0};
910 static const WCHAR sourcelist[] = {
911 'S','o','u','r','c','e','L','i','s','t',0};
912 static const WCHAR display_name[] = {
913 'D','i','s','p','l','a','y','N','a','m','e',0};
914 static const WCHAR display_version[] = {
915 'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
916 static const WCHAR assignment[] = {
917 'A','s','s','i','g','n','m','e','n','t',0};
918
919 TRACE("%s %s %p %p\n", debugstr_w(szProduct),
920 debugstr_w(szAttribute), szValue, pcchValueBuf);
921
922 if ((szValue->str.w && !pcchValueBuf) || !szProduct || !szAttribute)
923 return ERROR_INVALID_PARAMETER;
924
925 if (!squash_guid(szProduct, squished_pc))
926 return ERROR_INVALID_PARAMETER;
927
928 if ((r = MSIREG_OpenProductKey(szProduct, NULL,
929 MSIINSTALLCONTEXT_USERMANAGED,
930 &prodkey, FALSE)) != ERROR_SUCCESS &&
931 (r = MSIREG_OpenProductKey(szProduct, NULL,
932 MSIINSTALLCONTEXT_USERUNMANAGED,
933 &prodkey, FALSE)) != ERROR_SUCCESS &&
934 (r = MSIREG_OpenProductKey(szProduct, NULL,
935 MSIINSTALLCONTEXT_MACHINE,
936 &prodkey, FALSE)) == ERROR_SUCCESS)
937 {
938 context = MSIINSTALLCONTEXT_MACHINE;
939 }
940
941 MSIREG_OpenInstallProps(szProduct, context, NULL, &userdata, FALSE);
942
943 if (!lstrcmpW(szAttribute, INSTALLPROPERTY_HELPLINKW) ||
944 !lstrcmpW(szAttribute, INSTALLPROPERTY_HELPTELEPHONEW) ||
945 !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLDATEW) ||
946 !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW) ||
947 !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLLOCATIONW) ||
948 !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLSOURCEW) ||
949 !lstrcmpW(szAttribute, INSTALLPROPERTY_LOCALPACKAGEW) ||
950 !lstrcmpW(szAttribute, INSTALLPROPERTY_PUBLISHERW) ||
951 !lstrcmpW(szAttribute, INSTALLPROPERTY_URLINFOABOUTW) ||
952 !lstrcmpW(szAttribute, INSTALLPROPERTY_URLUPDATEINFOW) ||
953 !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONMINORW) ||
954 !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONMAJORW) ||
955 !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW) ||
956 !lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTIDW) ||
957 !lstrcmpW(szAttribute, INSTALLPROPERTY_REGCOMPANYW) ||
958 !lstrcmpW(szAttribute, INSTALLPROPERTY_REGOWNERW))
959 {
960 if (!prodkey)
961 {
962 r = ERROR_UNKNOWN_PRODUCT;
963 goto done;
964 }
965
966 if (!userdata)
967 return ERROR_UNKNOWN_PROPERTY;
968
969 if (!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW))
970 szAttribute = display_name;
971 else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW))
972 szAttribute = display_version;
973
974 val = msi_reg_get_value(userdata, szAttribute, &type);
975 if (!val)
976 val = empty;
977 }
978 else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTANCETYPEW) ||
979 !lstrcmpW(szAttribute, INSTALLPROPERTY_TRANSFORMSW) ||
980 !lstrcmpW(szAttribute, INSTALLPROPERTY_LANGUAGEW) ||
981 !lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTNAMEW) ||
982 !lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW) ||
983 !lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW) ||
984 !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONW) ||
985 !lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTICONW) ||
986 !lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGENAMEW) ||
987 !lstrcmpW(szAttribute, INSTALLPROPERTY_AUTHORIZED_LUA_APPW))
988 {
989 if (!prodkey)
990 {
991 r = ERROR_UNKNOWN_PRODUCT;
992 goto done;
993 }
994
995 if (!lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW))
996 szAttribute = assignment;
997
998 if (!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGENAMEW))
999 {
1000 res = RegOpenKeyW(prodkey, sourcelist, &source);
1001 if (res != ERROR_SUCCESS)
1002 {
1003 r = ERROR_UNKNOWN_PRODUCT;
1004 goto done;
1005 }
1006
1007 val = msi_reg_get_value(source, szAttribute, &type);
1008 if (!val)
1009 val = empty;
1010
1011 RegCloseKey(source);
1012 }
1013 else
1014 {
1015 val = msi_reg_get_value(prodkey, szAttribute, &type);
1016 if (!val)
1017 val = empty;
1018 }
1019
1020 if (val != empty && type != REG_DWORD &&
1021 !lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW))
1022 {
1023 if (lstrlenW(val) != SQUISH_GUID_SIZE - 1)
1024 badconfig = TRUE;
1025 else
1026 {
1027 unsquash_guid(val, packagecode);
1028 msi_free(val);
1029 val = strdupW(packagecode);
1030 }
1031 }
1032 }
1033
1034 if (!val)
1035 {
1036 r = ERROR_UNKNOWN_PROPERTY;
1037 goto done;
1038 }
1039
1040 if (pcchValueBuf)
1041 {
1042 save = *pcchValueBuf;
1043
1044 if (strlenW(val) < *pcchValueBuf)
1045 r = msi_strcpy_to_awstring(val, szValue, pcchValueBuf);
1046 else if (szValue->str.a || szValue->str.w)
1047 r = ERROR_MORE_DATA;
1048
1049 if (!badconfig)
1050 *pcchValueBuf = lstrlenW(val);
1051 else if (r == ERROR_SUCCESS)
1052 {
1053 *pcchValueBuf = save;
1054 r = ERROR_BAD_CONFIGURATION;
1055 }
1056 }
1057 else if (badconfig)
1058 r = ERROR_BAD_CONFIGURATION;
1059
1060 if (val != empty)
1061 msi_free(val);
1062
1063 done:
1064 RegCloseKey(prodkey);
1065 RegCloseKey(userdata);
1066 return r;
1067 }
1068
1069 UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute,
1070 LPSTR szBuffer, LPDWORD pcchValueBuf)
1071 {
1072 LPWSTR szwProduct, szwAttribute = NULL;
1073 UINT r = ERROR_OUTOFMEMORY;
1074 awstring buffer;
1075
1076 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szAttribute),
1077 szBuffer, pcchValueBuf);
1078
1079 szwProduct = strdupAtoW( szProduct );
1080 if( szProduct && !szwProduct )
1081 goto end;
1082
1083 szwAttribute = strdupAtoW( szAttribute );
1084 if( szAttribute && !szwAttribute )
1085 goto end;
1086
1087 buffer.unicode = FALSE;
1088 buffer.str.a = szBuffer;
1089
1090 r = MSI_GetProductInfo( szwProduct, szwAttribute,
1091 &buffer, pcchValueBuf );
1092
1093 end:
1094 msi_free( szwProduct );
1095 msi_free( szwAttribute );
1096
1097 return r;
1098 }
1099
1100 UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute,
1101 LPWSTR szBuffer, LPDWORD pcchValueBuf)
1102 {
1103 awstring buffer;
1104
1105 TRACE("%s %s %p %p\n", debugstr_w(szProduct), debugstr_w(szAttribute),
1106 szBuffer, pcchValueBuf);
1107
1108 buffer.unicode = TRUE;
1109 buffer.str.w = szBuffer;
1110
1111 return MSI_GetProductInfo( szProduct, szAttribute,
1112 &buffer, pcchValueBuf );
1113 }
1114
1115 UINT WINAPI MsiGetProductInfoExA(LPCSTR szProductCode, LPCSTR szUserSid,
1116 MSIINSTALLCONTEXT dwContext, LPCSTR szProperty,
1117 LPSTR szValue, LPDWORD pcchValue)
1118 {
1119 LPWSTR product = NULL;
1120 LPWSTR usersid = NULL;
1121 LPWSTR property = NULL;
1122 LPWSTR value = NULL;
1123 DWORD len = 0;
1124 UINT r;
1125
1126 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_a(szProductCode),
1127 debugstr_a(szUserSid), dwContext, debugstr_a(szProperty),
1128 szValue, pcchValue);
1129
1130 if (szValue && !pcchValue)
1131 return ERROR_INVALID_PARAMETER;
1132
1133 if (szProductCode) product = strdupAtoW(szProductCode);
1134 if (szUserSid) usersid = strdupAtoW(szUserSid);
1135 if (szProperty) property = strdupAtoW(szProperty);
1136
1137 r = MsiGetProductInfoExW(product, usersid, dwContext, property,
1138 NULL, &len);
1139 if (r != ERROR_SUCCESS)
1140 goto done;
1141
1142 value = msi_alloc(++len * sizeof(WCHAR));
1143 if (!value)
1144 {
1145 r = ERROR_OUTOFMEMORY;
1146 goto done;
1147 }
1148
1149 r = MsiGetProductInfoExW(product, usersid, dwContext, property,
1150 value, &len);
1151 if (r != ERROR_SUCCESS)
1152 goto done;
1153
1154 if (!pcchValue)
1155 goto done;
1156
1157 len = WideCharToMultiByte(CP_ACP, 0, value, -1, NULL, 0, NULL, NULL);
1158 if (*pcchValue >= len)
1159 WideCharToMultiByte(CP_ACP, 0, value, -1, szValue, len, NULL, NULL);
1160 else if (szValue)
1161 {
1162 r = ERROR_MORE_DATA;
1163 if (*pcchValue > 0)
1164 *szValue = '\0';
1165 }
1166
1167 if (*pcchValue <= len || !szValue)
1168 len = len * sizeof(WCHAR) - 1;
1169
1170 *pcchValue = len - 1;
1171
1172 done:
1173 msi_free(product);
1174 msi_free(usersid);
1175 msi_free(property);
1176 msi_free(value);
1177
1178 return r;
1179 }
1180
1181 static UINT msi_copy_outval(LPWSTR val, LPWSTR out, LPDWORD size)
1182 {
1183 UINT r;
1184
1185 if (!val)
1186 return ERROR_UNKNOWN_PROPERTY;
1187
1188 if (out)
1189 {
1190 if (strlenW(val) >= *size)
1191 {
1192 r = ERROR_MORE_DATA;
1193 if (*size > 0)
1194 *out = '\0';
1195 }
1196 else
1197 lstrcpyW(out, val);
1198 }
1199
1200 if (size)
1201 *size = lstrlenW(val);
1202
1203 return ERROR_SUCCESS;
1204 }
1205
1206 UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
1207 MSIINSTALLCONTEXT dwContext, LPCWSTR szProperty,
1208 LPWSTR szValue, LPDWORD pcchValue)
1209 {
1210 WCHAR squished_pc[GUID_SIZE];
1211 LPWSTR val = NULL;
1212 LPCWSTR package = NULL;
1213 HKEY props = NULL, prod;
1214 HKEY classes = NULL, managed;
1215 HKEY hkey = NULL;
1216 DWORD type;
1217 UINT r = ERROR_UNKNOWN_PRODUCT;
1218
1219 static const WCHAR one[] = {'1',0};
1220 static const WCHAR five[] = {'5',0};
1221 static const WCHAR empty[] = {0};
1222 static const WCHAR displayname[] = {
1223 'D','i','s','p','l','a','y','N','a','m','e',0};
1224 static const WCHAR displayversion[] = {
1225 'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
1226 static const WCHAR managed_local_package[] = {
1227 'M','a','n','a','g','e','d','L','o','c','a','l',
1228 'P','a','c','k','a','g','e',0};
1229
1230 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_w(szProductCode),
1231 debugstr_w(szUserSid), dwContext, debugstr_w(szProperty),
1232 szValue, pcchValue);
1233
1234 if (!szProductCode || !squash_guid(szProductCode, squished_pc))
1235 return ERROR_INVALID_PARAMETER;
1236
1237 if (szValue && !pcchValue)
1238 return ERROR_INVALID_PARAMETER;
1239
1240 if (dwContext != MSIINSTALLCONTEXT_USERUNMANAGED &&
1241 dwContext != MSIINSTALLCONTEXT_USERMANAGED &&
1242 dwContext != MSIINSTALLCONTEXT_MACHINE)
1243 return ERROR_INVALID_PARAMETER;
1244
1245 if (!szProperty || !*szProperty)
1246 return ERROR_INVALID_PARAMETER;
1247
1248 if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
1249 return ERROR_INVALID_PARAMETER;
1250
1251 /* FIXME: dwContext is provided, no need to search for it */
1252 MSIREG_OpenProductKey(szProductCode, NULL,MSIINSTALLCONTEXT_USERMANAGED,
1253 &managed, FALSE);
1254 MSIREG_OpenProductKey(szProductCode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1255 &prod, FALSE);
1256
1257 MSIREG_OpenInstallProps(szProductCode, dwContext, NULL, &props, FALSE);
1258
1259 if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
1260 {
1261 package = INSTALLPROPERTY_LOCALPACKAGEW;
1262
1263 if (!props && !prod)
1264 goto done;
1265 }
1266 else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
1267 {
1268 package = managed_local_package;
1269
1270 if (!props && !managed)
1271 goto done;
1272 }
1273 else if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1274 {
1275 package = INSTALLPROPERTY_LOCALPACKAGEW;
1276 MSIREG_OpenProductKey(szProductCode, NULL, dwContext, &classes, FALSE);
1277
1278 if (!props && !classes)
1279 goto done;
1280 }
1281
1282 if (!lstrcmpW(szProperty, INSTALLPROPERTY_HELPLINKW) ||
1283 !lstrcmpW(szProperty, INSTALLPROPERTY_HELPTELEPHONEW) ||
1284 !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLDATEW) ||
1285 !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW) ||
1286 !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLLOCATIONW) ||
1287 !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLSOURCEW) ||
1288 !lstrcmpW(szProperty, INSTALLPROPERTY_LOCALPACKAGEW) ||
1289 !lstrcmpW(szProperty, INSTALLPROPERTY_PUBLISHERW) ||
1290 !lstrcmpW(szProperty, INSTALLPROPERTY_URLINFOABOUTW) ||
1291 !lstrcmpW(szProperty, INSTALLPROPERTY_URLUPDATEINFOW) ||
1292 !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONMINORW) ||
1293 !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONMAJORW) ||
1294 !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONSTRINGW) ||
1295 !lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTIDW) ||
1296 !lstrcmpW(szProperty, INSTALLPROPERTY_REGCOMPANYW) ||
1297 !lstrcmpW(szProperty, INSTALLPROPERTY_REGOWNERW) ||
1298 !lstrcmpW(szProperty, INSTALLPROPERTY_INSTANCETYPEW))
1299 {
1300 val = msi_reg_get_value(props, package, &type);
1301 if (!val)
1302 {
1303 if (prod || classes)
1304 r = ERROR_UNKNOWN_PROPERTY;
1305
1306 goto done;
1307 }
1308
1309 msi_free(val);
1310
1311 if (!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW))
1312 szProperty = displayname;
1313 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONSTRINGW))
1314 szProperty = displayversion;
1315
1316 val = msi_reg_get_value(props, szProperty, &type);
1317 if (!val)
1318 val = strdupW(empty);
1319
1320 r = msi_copy_outval(val, szValue, pcchValue);
1321 }
1322 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_TRANSFORMSW) ||
1323 !lstrcmpW(szProperty, INSTALLPROPERTY_LANGUAGEW) ||
1324 !lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTNAMEW) ||
1325 !lstrcmpW(szProperty, INSTALLPROPERTY_PACKAGECODEW) ||
1326 !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONW) ||
1327 !lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTICONW) ||
1328 !lstrcmpW(szProperty, INSTALLPROPERTY_PACKAGENAMEW) ||
1329 !lstrcmpW(szProperty, INSTALLPROPERTY_AUTHORIZED_LUA_APPW))
1330 {
1331 if (!prod && !classes)
1332 goto done;
1333
1334 if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
1335 hkey = prod;
1336 else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
1337 hkey = managed;
1338 else if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1339 hkey = classes;
1340
1341 val = msi_reg_get_value(hkey, szProperty, &type);
1342 if (!val)
1343 val = strdupW(empty);
1344
1345 r = msi_copy_outval(val, szValue, pcchValue);
1346 }
1347 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTSTATEW))
1348 {
1349 if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1350 {
1351 if (props)
1352 {
1353 val = msi_reg_get_value(props, package, &type);
1354 if (!val)
1355 goto done;
1356
1357 msi_free(val);
1358 val = strdupW(five);
1359 }
1360 else
1361 val = strdupW(one);
1362
1363 r = msi_copy_outval(val, szValue, pcchValue);
1364 goto done;
1365 }
1366 else if (props && (val = msi_reg_get_value(props, package, &type)))
1367 {
1368 msi_free(val);
1369 val = strdupW(five);
1370 r = msi_copy_outval(val, szValue, pcchValue);
1371 goto done;
1372 }
1373
1374 if (prod || managed)
1375 val = strdupW(one);
1376 else
1377 goto done;
1378
1379 r = msi_copy_outval(val, szValue, pcchValue);
1380 }
1381 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_ASSIGNMENTTYPEW))
1382 {
1383 if (!prod && !classes)
1384 goto done;
1385
1386 /* FIXME */
1387 val = strdupW(empty);
1388 r = msi_copy_outval(val, szValue, pcchValue);
1389 }
1390 else
1391 r = ERROR_UNKNOWN_PROPERTY;
1392
1393 done:
1394 RegCloseKey(props);
1395 RegCloseKey(prod);
1396 RegCloseKey(managed);
1397 RegCloseKey(classes);
1398 msi_free(val);
1399
1400 return r;
1401 }
1402
1403 UINT WINAPI MsiGetPatchInfoExA(LPCSTR szPatchCode, LPCSTR szProductCode,
1404 LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1405 LPCSTR szProperty, LPSTR lpValue, DWORD *pcchValue)
1406 {
1407 LPWSTR patch = NULL, product = NULL, usersid = NULL;
1408 LPWSTR property = NULL, val = NULL;
1409 DWORD len;
1410 UINT r;
1411
1412 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_a(szPatchCode),
1413 debugstr_a(szProductCode), debugstr_a(szUserSid), dwContext,
1414 debugstr_a(szProperty), lpValue, pcchValue);
1415
1416 if (lpValue && !pcchValue)
1417 return ERROR_INVALID_PARAMETER;
1418
1419 if (szPatchCode) patch = strdupAtoW(szPatchCode);
1420 if (szProductCode) product = strdupAtoW(szProductCode);
1421 if (szUserSid) usersid = strdupAtoW(szUserSid);
1422 if (szProperty) property = strdupAtoW(szProperty);
1423
1424 len = 0;
1425 r = MsiGetPatchInfoExW(patch, product, usersid, dwContext, property,
1426 NULL, &len);
1427 if (r != ERROR_SUCCESS)
1428 goto done;
1429
1430 val = msi_alloc(++len * sizeof(WCHAR));
1431 if (!val)
1432 {
1433 r = ERROR_OUTOFMEMORY;
1434 goto done;
1435 }
1436
1437 r = MsiGetPatchInfoExW(patch, product, usersid, dwContext, property,
1438 val, &len);
1439 if (r != ERROR_SUCCESS || !pcchValue)
1440 goto done;
1441
1442 if (lpValue)
1443 WideCharToMultiByte(CP_ACP, 0, val, -1, lpValue,
1444 *pcchValue - 1, NULL, NULL);
1445
1446 len = lstrlenW(val);
1447 if ((*val && *pcchValue < len + 1) || !lpValue)
1448 {
1449 if (lpValue)
1450 {
1451 r = ERROR_MORE_DATA;
1452 lpValue[*pcchValue - 1] = '\0';
1453 }
1454
1455 *pcchValue = len * sizeof(WCHAR);
1456 }
1457 else
1458 *pcchValue = len;
1459
1460 done:
1461 msi_free(val);
1462 msi_free(patch);
1463 msi_free(product);
1464 msi_free(usersid);
1465 msi_free(property);
1466
1467 return r;
1468 }
1469
1470 UINT WINAPI MsiGetPatchInfoExW(LPCWSTR szPatchCode, LPCWSTR szProductCode,
1471 LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1472 LPCWSTR szProperty, LPWSTR lpValue, DWORD *pcchValue)
1473 {
1474 WCHAR squished_pc[GUID_SIZE];
1475 WCHAR squished_patch[GUID_SIZE];
1476 HKEY udprod = 0, prod = 0, props = 0;
1477 HKEY patch = 0, patches = 0;
1478 HKEY udpatch = 0, datakey = 0;
1479 HKEY prodpatches = 0;
1480 LPWSTR val = NULL;
1481 UINT r = ERROR_UNKNOWN_PRODUCT;
1482 DWORD len;
1483 LONG res;
1484
1485 static const WCHAR szEmpty[] = {0};
1486 static const WCHAR szPatches[] = {'P','a','t','c','h','e','s',0};
1487 static const WCHAR szInstalled[] = {'I','n','s','t','a','l','l','e','d',0};
1488 static const WCHAR szManagedPackage[] = {'M','a','n','a','g','e','d',
1489 'L','o','c','a','l','P','a','c','k','a','g','e',0};
1490
1491 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_w(szPatchCode),
1492 debugstr_w(szProductCode), debugstr_w(szUserSid), dwContext,
1493 debugstr_w(szProperty), lpValue, pcchValue);
1494
1495 if (!szProductCode || !squash_guid(szProductCode, squished_pc))
1496 return ERROR_INVALID_PARAMETER;
1497
1498 if (!szPatchCode || !squash_guid(szPatchCode, squished_patch))
1499 return ERROR_INVALID_PARAMETER;
1500
1501 if (!szProperty)
1502 return ERROR_INVALID_PARAMETER;
1503
1504 if (lpValue && !pcchValue)
1505 return ERROR_INVALID_PARAMETER;
1506
1507 if (dwContext != MSIINSTALLCONTEXT_USERMANAGED &&
1508 dwContext != MSIINSTALLCONTEXT_USERUNMANAGED &&
1509 dwContext != MSIINSTALLCONTEXT_MACHINE)
1510 return ERROR_INVALID_PARAMETER;
1511
1512 if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
1513 return ERROR_INVALID_PARAMETER;
1514
1515 if (!lstrcmpW(szUserSid, szLocalSid))
1516 return ERROR_INVALID_PARAMETER;
1517
1518 if (MSIREG_OpenUserDataProductKey(szProductCode, dwContext, NULL,
1519 &udprod, FALSE) != ERROR_SUCCESS)
1520 goto done;
1521
1522 if (MSIREG_OpenInstallProps(szProductCode, dwContext, NULL,
1523 &props, FALSE) != ERROR_SUCCESS)
1524 goto done;
1525
1526 r = ERROR_UNKNOWN_PATCH;
1527
1528 res = RegOpenKeyExW(udprod, szPatches, 0, KEY_READ, &patches);
1529 if (res != ERROR_SUCCESS)
1530 goto done;
1531
1532 res = RegOpenKeyExW(patches, squished_patch, 0, KEY_READ, &patch);
1533 if (res != ERROR_SUCCESS)
1534 goto done;
1535
1536 if (!lstrcmpW(szProperty, INSTALLPROPERTY_TRANSFORMSW))
1537 {
1538 if (MSIREG_OpenProductKey(szProductCode, NULL, dwContext,
1539 &prod, FALSE) != ERROR_SUCCESS)
1540 goto done;
1541
1542 res = RegOpenKeyExW(prod, szPatches, 0, KEY_ALL_ACCESS, &prodpatches);
1543 if (res != ERROR_SUCCESS)
1544 goto done;
1545
1546 datakey = prodpatches;
1547 szProperty = squished_patch;
1548 }
1549 else
1550 {
1551 if (MSIREG_OpenUserDataPatchKey(szPatchCode, dwContext,
1552 &udpatch, FALSE) != ERROR_SUCCESS)
1553 goto done;
1554
1555 if (!lstrcmpW(szProperty, INSTALLPROPERTY_LOCALPACKAGEW))
1556 {
1557 if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
1558 szProperty = szManagedPackage;
1559 datakey = udpatch;
1560 }
1561 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLDATEW))
1562 {
1563 datakey = patch;
1564 szProperty = szInstalled;
1565 }
1566 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_LOCALPACKAGEW))
1567 {
1568 datakey = udpatch;
1569 }
1570 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_UNINSTALLABLEW) ||
1571 !lstrcmpW(szProperty, INSTALLPROPERTY_PATCHSTATEW) ||
1572 !lstrcmpW(szProperty, INSTALLPROPERTY_DISPLAYNAMEW) ||
1573 !lstrcmpW(szProperty, INSTALLPROPERTY_MOREINFOURLW))
1574 {
1575 datakey = patch;
1576 }
1577 else
1578 {
1579 r = ERROR_UNKNOWN_PROPERTY;
1580 goto done;
1581 }
1582 }
1583
1584 val = msi_reg_get_val_str(datakey, szProperty);
1585 if (!val)
1586 val = strdupW(szEmpty);
1587
1588 r = ERROR_SUCCESS;
1589
1590 if (!pcchValue)
1591 goto done;
1592
1593 if (lpValue)
1594 lstrcpynW(lpValue, val, *pcchValue);
1595
1596 len = lstrlenW(val);
1597 if ((*val && *pcchValue < len + 1) || !lpValue)
1598 {
1599 if (lpValue)
1600 r = ERROR_MORE_DATA;
1601
1602 *pcchValue = len * sizeof(WCHAR);
1603 }
1604
1605 *pcchValue = len;
1606
1607 done:
1608 msi_free(val);
1609 RegCloseKey(prodpatches);
1610 RegCloseKey(prod);
1611 RegCloseKey(patch);
1612 RegCloseKey(patches);
1613 RegCloseKey(udpatch);
1614 RegCloseKey(props);
1615 RegCloseKey(udprod);
1616
1617 return r;
1618 }
1619
1620 UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes)
1621 {
1622 LPWSTR szwLogFile = NULL;
1623 UINT r;
1624
1625 TRACE("%08x %s %08x\n", dwLogMode, debugstr_a(szLogFile), attributes);
1626
1627 if( szLogFile )
1628 {
1629 szwLogFile = strdupAtoW( szLogFile );
1630 if( !szwLogFile )
1631 return ERROR_OUTOFMEMORY;
1632 }
1633 r = MsiEnableLogW( dwLogMode, szwLogFile, attributes );
1634 msi_free( szwLogFile );
1635 return r;
1636 }
1637
1638 UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, DWORD attributes)
1639 {
1640 HANDLE file = INVALID_HANDLE_VALUE;
1641
1642 TRACE("%08x %s %08x\n", dwLogMode, debugstr_w(szLogFile), attributes);
1643
1644 if (szLogFile)
1645 {
1646 lstrcpyW(gszLogFile,szLogFile);
1647 if (!(attributes & INSTALLLOGATTRIBUTES_APPEND))
1648 DeleteFileW(szLogFile);
1649 file = CreateFileW(szLogFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
1650 FILE_ATTRIBUTE_NORMAL, NULL);
1651 if (file != INVALID_HANDLE_VALUE)
1652 CloseHandle(file);
1653 else
1654 ERR("Unable to enable log %s\n",debugstr_w(szLogFile));
1655 }
1656 else
1657 gszLogFile[0] = '\0';
1658
1659 return ERROR_SUCCESS;
1660 }
1661
1662 UINT WINAPI MsiEnumComponentCostsW(MSIHANDLE hInstall, LPCWSTR szComponent,
1663 DWORD dwIndex, INSTALLSTATE iState,
1664 LPWSTR lpDriveBuf, DWORD *pcchDriveBuf,
1665 int *piCost, int *pTempCost)
1666 {
1667 FIXME("(%d, %s, %d, %d, %p, %p, %p %p): stub!\n", hInstall,
1668 debugstr_w(szComponent), dwIndex, iState, lpDriveBuf,
1669 pcchDriveBuf, piCost, pTempCost);
1670
1671 return ERROR_NO_MORE_ITEMS;
1672 }
1673
1674 UINT WINAPI MsiQueryComponentStateA(LPCSTR szProductCode,
1675 LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1676 LPCSTR szComponent, INSTALLSTATE *pdwState)
1677 {
1678 LPWSTR prodcode = NULL, usersid = NULL, comp = NULL;
1679 UINT r;
1680
1681 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_a(szProductCode),
1682 debugstr_a(szUserSid), dwContext, debugstr_a(szComponent), pdwState);
1683
1684 if (szProductCode && !(prodcode = strdupAtoW(szProductCode)))
1685 return ERROR_OUTOFMEMORY;
1686
1687 if (szUserSid && !(usersid = strdupAtoW(szUserSid)))
1688 return ERROR_OUTOFMEMORY;
1689
1690 if (szComponent && !(comp = strdupAtoW(szComponent)))
1691 return ERROR_OUTOFMEMORY;
1692
1693 r = MsiQueryComponentStateW(prodcode, usersid, dwContext, comp, pdwState);
1694
1695 msi_free(prodcode);
1696 msi_free(usersid);
1697 msi_free(comp);
1698
1699 return r;
1700 }
1701
1702 static BOOL msi_comp_find_prod_key(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
1703 {
1704 UINT r;
1705 HKEY hkey;
1706
1707 r = MSIREG_OpenProductKey(prodcode, NULL, context, &hkey, FALSE);
1708 RegCloseKey(hkey);
1709 return (r == ERROR_SUCCESS);
1710 }
1711
1712 static BOOL msi_comp_find_package(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
1713 {
1714 LPCWSTR package;
1715 HKEY hkey;
1716 DWORD sz;
1717 LONG res;
1718 UINT r;
1719
1720 static const WCHAR local_package[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0};
1721 static const WCHAR managed_local_package[] = {
1722 'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0
1723 };
1724
1725 r = MSIREG_OpenInstallProps(prodcode, context, NULL, &hkey, FALSE);
1726 if (r != ERROR_SUCCESS)
1727 return FALSE;
1728
1729 if (context == MSIINSTALLCONTEXT_USERMANAGED)
1730 package = managed_local_package;
1731 else
1732 package = local_package;
1733
1734 sz = 0;
1735 res = RegQueryValueExW(hkey, package, NULL, NULL, NULL, &sz);
1736 RegCloseKey(hkey);
1737
1738 return (res == ERROR_SUCCESS);
1739 }
1740
1741 static BOOL msi_comp_find_prodcode(LPWSTR squished_pc,
1742 MSIINSTALLCONTEXT context,
1743 LPCWSTR comp, LPWSTR val, DWORD *sz)
1744 {
1745 HKEY hkey;
1746 LONG res;
1747 UINT r;
1748
1749 if (context == MSIINSTALLCONTEXT_MACHINE)
1750 r = MSIREG_OpenUserDataComponentKey(comp, szLocalSid, &hkey, FALSE);
1751 else
1752 r = MSIREG_OpenUserDataComponentKey(comp, NULL, &hkey, FALSE);
1753
1754 if (r != ERROR_SUCCESS)
1755 return FALSE;
1756
1757 res = RegQueryValueExW(hkey, squished_pc, NULL, NULL, (BYTE *)val, sz);
1758 if (res != ERROR_SUCCESS)
1759 return FALSE;
1760
1761 RegCloseKey(hkey);
1762 return TRUE;
1763 }
1764
1765 UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode,
1766 LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1767 LPCWSTR szComponent, INSTALLSTATE *pdwState)
1768 {
1769 WCHAR squished_pc[GUID_SIZE];
1770 WCHAR val[MAX_PATH];
1771 BOOL found;
1772 DWORD sz;
1773
1774 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_w(szProductCode),
1775 debugstr_w(szUserSid), dwContext, debugstr_w(szComponent), pdwState);
1776
1777 if (!pdwState || !szComponent)
1778 return ERROR_INVALID_PARAMETER;
1779
1780 if (!szProductCode || !*szProductCode || lstrlenW(szProductCode) != GUID_SIZE - 1)
1781 return ERROR_INVALID_PARAMETER;
1782
1783 if (!squash_guid(szProductCode, squished_pc))
1784 return ERROR_INVALID_PARAMETER;
1785
1786 found = msi_comp_find_prod_key(szProductCode, dwContext);
1787
1788 if (!msi_comp_find_package(szProductCode, dwContext))
1789 {
1790 if (found)
1791 {
1792 *pdwState = INSTALLSTATE_UNKNOWN;
1793 return ERROR_UNKNOWN_COMPONENT;
1794 }
1795
1796 return ERROR_UNKNOWN_PRODUCT;
1797 }
1798
1799 *pdwState = INSTALLSTATE_UNKNOWN;
1800
1801 sz = MAX_PATH;
1802 if (!msi_comp_find_prodcode(squished_pc, dwContext, szComponent, val, &sz))
1803 return ERROR_UNKNOWN_COMPONENT;
1804
1805 if (sz == 0)
1806 *pdwState = INSTALLSTATE_NOTUSED;
1807 else
1808 {
1809 if (lstrlenW(val) > 2 &&
1810 val[0] >= '0' && val[0] <= '9' && val[1] >= '0' && val[1] <= '9')
1811 {
1812 *pdwState = INSTALLSTATE_SOURCE;
1813 }
1814 else
1815 *pdwState = INSTALLSTATE_LOCAL;
1816 }
1817
1818 return ERROR_SUCCESS;
1819 }
1820
1821 INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct)
1822 {
1823 LPWSTR szwProduct = NULL;
1824 INSTALLSTATE r;
1825
1826 if( szProduct )
1827 {
1828 szwProduct = strdupAtoW( szProduct );
1829 if( !szwProduct )
1830 return ERROR_OUTOFMEMORY;
1831 }
1832 r = MsiQueryProductStateW( szwProduct );
1833 msi_free( szwProduct );
1834 return r;
1835 }
1836
1837 INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct)
1838 {
1839 MSIINSTALLCONTEXT context = MSIINSTALLCONTEXT_USERUNMANAGED;
1840 INSTALLSTATE state = INSTALLSTATE_ADVERTISED;
1841 HKEY prodkey = 0, userdata = 0;
1842 DWORD val;
1843 UINT r;
1844
1845 static const WCHAR szWindowsInstaller[] = {
1846 'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
1847
1848 TRACE("%s\n", debugstr_w(szProduct));
1849
1850 if (!szProduct || !*szProduct)
1851 return INSTALLSTATE_INVALIDARG;
1852
1853 if (lstrlenW(szProduct) != GUID_SIZE - 1)
1854 return INSTALLSTATE_INVALIDARG;
1855
1856 if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
1857 &prodkey, FALSE) != ERROR_SUCCESS &&
1858 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1859 &prodkey, FALSE) != ERROR_SUCCESS &&
1860 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
1861 &prodkey, FALSE) == ERROR_SUCCESS)
1862 {
1863 context = MSIINSTALLCONTEXT_MACHINE;
1864 }
1865
1866 r = MSIREG_OpenInstallProps(szProduct, context, NULL, &userdata, FALSE);
1867 if (r != ERROR_SUCCESS)
1868 goto done;
1869
1870 if (!msi_reg_get_val_dword(userdata, szWindowsInstaller, &val))
1871 goto done;
1872
1873 if (val)
1874 state = INSTALLSTATE_DEFAULT;
1875 else
1876 state = INSTALLSTATE_UNKNOWN;
1877
1878 done:
1879 if (!prodkey)
1880 {
1881 state = INSTALLSTATE_UNKNOWN;
1882
1883 if (userdata)
1884 state = INSTALLSTATE_ABSENT;
1885 }
1886
1887 RegCloseKey(prodkey);
1888 RegCloseKey(userdata);
1889 return state;
1890 }
1891
1892 INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd)
1893 {
1894 INSTALLUILEVEL old = gUILevel;
1895 HWND oldwnd = gUIhwnd;
1896
1897 TRACE("%08x %p\n", dwUILevel, phWnd);
1898
1899 gUILevel = dwUILevel;
1900 if (phWnd)
1901 {
1902 gUIhwnd = *phWnd;
1903 *phWnd = oldwnd;
1904 }
1905 return old;
1906 }
1907
1908 INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler,
1909 DWORD dwMessageFilter, LPVOID pvContext)
1910 {
1911 INSTALLUI_HANDLERA prev = gUIHandlerA;
1912
1913 TRACE("%p %x %p\n",puiHandler, dwMessageFilter,pvContext);
1914 gUIHandlerA = puiHandler;
1915 gUIFilter = dwMessageFilter;
1916 gUIContext = pvContext;
1917
1918 return prev;
1919 }
1920
1921 INSTALLUI_HANDLERW WINAPI MsiSetExternalUIW(INSTALLUI_HANDLERW puiHandler,
1922 DWORD dwMessageFilter, LPVOID pvContext)
1923 {
1924 INSTALLUI_HANDLERW prev = gUIHandlerW;
1925
1926 TRACE("%p %x %p\n",puiHandler,dwMessageFilter,pvContext);
1927 gUIHandlerW = puiHandler;
1928 gUIFilter = dwMessageFilter;
1929 gUIContext = pvContext;
1930
1931 return prev;
1932 }
1933
1934 /******************************************************************
1935 * MsiLoadStringW [MSI.@]
1936 *
1937 * Loads a string from MSI's string resources.
1938 *
1939 * PARAMS
1940 *
1941 * handle [I] only -1 is handled currently
1942 * id [I] id of the string to be loaded
1943 * lpBuffer [O] buffer for the string to be written to
1944 * nBufferMax [I] maximum size of the buffer in characters
1945 * lang [I] the preferred language for the string
1946 *
1947 * RETURNS
1948 *
1949 * If successful, this function returns the language id of the string loaded
1950 * If the function fails, the function returns zero.
1951 *
1952 * NOTES
1953 *
1954 * The type of the first parameter is unknown. LoadString's prototype
1955 * suggests that it might be a module handle. I have made it an MSI handle
1956 * for starters, as -1 is an invalid MSI handle, but not an invalid module
1957 * handle. Maybe strings can be stored in an MSI database somehow.
1958 */
1959 LANGID WINAPI MsiLoadStringW( MSIHANDLE handle, UINT id, LPWSTR lpBuffer,
1960 int nBufferMax, LANGID lang )
1961 {
1962 HRSRC hres;
1963 HGLOBAL hResData;
1964 LPWSTR p;
1965 DWORD i, len;
1966
1967 TRACE("%d %u %p %d %d\n", handle, id, lpBuffer, nBufferMax, lang);
1968
1969 if( handle != -1 )
1970 FIXME("don't know how to deal with handle = %08x\n", handle);
1971
1972 if( !lang )
1973 lang = GetUserDefaultLangID();
1974
1975 hres = FindResourceExW( msi_hInstance, (LPCWSTR) RT_STRING,
1976 (LPWSTR)1, lang );
1977 if( !hres )
1978 return 0;
1979 hResData = LoadResource( msi_hInstance, hres );
1980 if( !hResData )
1981 return 0;
1982 p = LockResource( hResData );
1983 if( !p )
1984 return 0;
1985
1986 for (i = 0; i < (id&0xf); i++)
1987 p += *p + 1;
1988 len = *p;
1989
1990 if( nBufferMax <= len )
1991 return 0;
1992
1993 memcpy( lpBuffer, p+1, len * sizeof(WCHAR));
1994 lpBuffer[ len ] = 0;
1995
1996 TRACE("found -> %s\n", debugstr_w(lpBuffer));
1997
1998 return lang;
1999 }
2000
2001 LANGID WINAPI MsiLoadStringA( MSIHANDLE handle, UINT id, LPSTR lpBuffer,
2002 int nBufferMax, LANGID lang )
2003 {
2004 LPWSTR bufW;
2005 LANGID r;
2006 INT len;
2007
2008 bufW = msi_alloc(nBufferMax*sizeof(WCHAR));
2009 r = MsiLoadStringW(handle, id, bufW, nBufferMax, lang);
2010 if( r )
2011 {
2012 len = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL );
2013 if( len <= nBufferMax )
2014 WideCharToMultiByte( CP_ACP, 0, bufW, -1,
2015 lpBuffer, nBufferMax, NULL, NULL );
2016 else
2017 r = 0;
2018 }
2019 msi_free(bufW);
2020 return r;
2021 }
2022
2023 INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf,
2024 LPDWORD pcchBuf)
2025 {
2026 char szProduct[GUID_SIZE];
2027
2028 TRACE("%s %p %p\n", debugstr_a(szComponent), lpPathBuf, pcchBuf);
2029
2030 if (MsiGetProductCodeA( szComponent, szProduct ) != ERROR_SUCCESS)
2031 return INSTALLSTATE_UNKNOWN;
2032
2033 return MsiGetComponentPathA( szProduct, szComponent, lpPathBuf, pcchBuf );
2034 }
2035
2036 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPWSTR lpPathBuf,
2037 LPDWORD pcchBuf)
2038 {
2039 WCHAR szProduct[GUID_SIZE];
2040
2041 TRACE("%s %p %p\n", debugstr_w(szComponent), lpPathBuf, pcchBuf);
2042
2043 if (MsiGetProductCodeW( szComponent, szProduct ) != ERROR_SUCCESS)
2044 return INSTALLSTATE_UNKNOWN;
2045
2046 return MsiGetComponentPathW( szProduct, szComponent, lpPathBuf, pcchBuf );
2047 }
2048
2049 UINT WINAPI MsiMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType,
2050 WORD wLanguageId, DWORD f)
2051 {
2052 FIXME("%p %s %s %u %08x %08x\n", hWnd, debugstr_a(lpText), debugstr_a(lpCaption),
2053 uType, wLanguageId, f);
2054 return MessageBoxExA(hWnd,lpText,lpCaption,uType,wLanguageId);
2055 }
2056
2057 UINT WINAPI MsiMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType,
2058 WORD wLanguageId, DWORD f)
2059 {
2060 FIXME("%p %s %s %u %08x %08x\n", hWnd, debugstr_w(lpText), debugstr_w(lpCaption),
2061 uType, wLanguageId, f);
2062 return MessageBoxExW(hWnd,lpText,lpCaption,uType,wLanguageId);
2063 }
2064
2065 UINT WINAPI MsiProvideAssemblyA( LPCSTR szAssemblyName, LPCSTR szAppContext,
2066 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf,
2067 LPDWORD pcchPathBuf )
2068 {
2069 FIXME("%s %s %08x %08x %p %p\n", debugstr_a(szAssemblyName),
2070 debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
2071 pcchPathBuf);
2072 return ERROR_CALL_NOT_IMPLEMENTED;
2073 }
2074
2075 UINT WINAPI MsiProvideAssemblyW( LPCWSTR szAssemblyName, LPCWSTR szAppContext,
2076 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf,
2077 LPDWORD pcchPathBuf )
2078 {
2079 FIXME("%s %s %08x %08x %p %p\n", debugstr_w(szAssemblyName),
2080 debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
2081 pcchPathBuf);
2082 return ERROR_CALL_NOT_IMPLEMENTED;
2083 }
2084
2085 UINT WINAPI MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor,
2086 LPSTR szPath, LPDWORD pcchPath, LPDWORD pcchArgs )
2087 {
2088 FIXME("%s %p %p %p\n", debugstr_a(szDescriptor), szPath, pcchPath, pcchArgs );
2089 return ERROR_CALL_NOT_IMPLEMENTED;
2090 }
2091
2092 UINT WINAPI MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor,
2093 LPWSTR szPath, LPDWORD pcchPath, LPDWORD pcchArgs )
2094 {
2095 FIXME("%s %p %p %p\n", debugstr_w(szDescriptor), szPath, pcchPath, pcchArgs );
2096 return ERROR_CALL_NOT_IMPLEMENTED;
2097 }
2098
2099 HRESULT WINAPI MsiGetFileSignatureInformationA( LPCSTR szSignedObjectPath,
2100 DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, LPBYTE pbHashData,
2101 LPDWORD pcbHashData)
2102 {
2103 FIXME("%s %08x %p %p %p\n", debugstr_a(szSignedObjectPath), dwFlags,
2104 ppcCertContext, pbHashData, pcbHashData);
2105 return ERROR_CALL_NOT_IMPLEMENTED;
2106 }
2107
2108 HRESULT WINAPI MsiGetFileSignatureInformationW( LPCWSTR szSignedObjectPath,
2109 DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, LPBYTE pbHashData,
2110 LPDWORD pcbHashData)
2111 {
2112 FIXME("%s %08x %p %p %p\n", debugstr_w(szSignedObjectPath), dwFlags,
2113 ppcCertContext, pbHashData, pcbHashData);
2114 return ERROR_CALL_NOT_IMPLEMENTED;
2115 }
2116
2117 /******************************************************************
2118 * MsiGetProductPropertyA [MSI.@]
2119 */
2120 UINT WINAPI MsiGetProductPropertyA(MSIHANDLE hProduct, LPCSTR szProperty,
2121 LPSTR szValue, LPDWORD pccbValue)
2122 {
2123 LPWSTR prop = NULL, val = NULL;
2124 DWORD len;
2125 UINT r;
2126
2127 TRACE("(%d, %s, %p, %p)\n", hProduct, debugstr_a(szProperty),
2128 szValue, pccbValue);
2129
2130 if (szValue && !pccbValue)
2131 return ERROR_INVALID_PARAMETER;
2132
2133 if (szProperty) prop = strdupAtoW(szProperty);
2134
2135 len = 0;
2136 r = MsiGetProductPropertyW(hProduct, prop, NULL, &len);
2137 if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
2138 goto done;
2139
2140 if (r == ERROR_SUCCESS)
2141 {
2142 if (szValue) *szValue = '\0';
2143 if (pccbValue) *pccbValue = 0;
2144 goto done;
2145 }
2146
2147 val = msi_alloc(++len * sizeof(WCHAR));
2148 if (!val)
2149 {
2150 r = ERROR_OUTOFMEMORY;
2151 goto done;
2152 }
2153
2154 r = MsiGetProductPropertyW(hProduct, prop, val, &len);
2155 if (r != ERROR_SUCCESS)
2156 goto done;
2157
2158 len = WideCharToMultiByte(CP_ACP, 0, val, -1, NULL, 0, NULL, NULL);
2159
2160 if (szValue)
2161 WideCharToMultiByte(CP_ACP, 0, val, -1, szValue,
2162 *pccbValue, NULL, NULL);
2163
2164 if (pccbValue)
2165 {
2166 if (len > *pccbValue)
2167 r = ERROR_MORE_DATA;
2168
2169 *pccbValue = len - 1;
2170 }
2171
2172 done:
2173 msi_free(prop);
2174 msi_free(val);
2175
2176 return r;
2177 }
2178
2179 /******************************************************************
2180 * MsiGetProductPropertyW [MSI.@]
2181 */
2182 UINT WINAPI MsiGetProductPropertyW(MSIHANDLE hProduct, LPCWSTR szProperty,
2183 LPWSTR szValue, LPDWORD pccbValue)
2184 {
2185 MSIPACKAGE *package;
2186 MSIQUERY *view = NULL;
2187 MSIRECORD *rec = NULL;
2188 LPCWSTR val;
2189 UINT r;
2190
2191 static const WCHAR query[] = {
2192 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
2193 '`','P','r','o','p','e','r','t','y','`',' ','W','H','E','R','E',' ',
2194 '`','P','r','o','p','e','r','t','y','`','=','\'','%','s','\'',0};
2195
2196 TRACE("(%d, %s, %p, %p)\n", hProduct, debugstr_w(szProperty),
2197 szValue, pccbValue);
2198
2199 if (!szProperty)
2200 return ERROR_INVALID_PARAMETER;
2201
2202 if (szValue && !pccbValue)
2203 return ERROR_INVALID_PARAMETER;
2204
2205 package = msihandle2msiinfo(hProduct, MSIHANDLETYPE_PACKAGE);
2206 if (!package)
2207 return ERROR_INVALID_HANDLE;
2208
2209 r = MSI_OpenQuery(package->db, &view, query, szProperty);
2210 if (r != ERROR_SUCCESS)
2211 goto done;
2212
2213 r = MSI_ViewExecute(view, 0);
2214 if (r != ERROR_SUCCESS)
2215 goto done;
2216
2217 r = MSI_ViewFetch(view, &rec);
2218 if (r != ERROR_SUCCESS)
2219 goto done;
2220
2221 val = MSI_RecordGetString(rec, 2);
2222 if (!val)
2223 goto done;
2224
2225 if (lstrlenW(val) >= *pccbValue)
2226 {
2227 lstrcpynW(szValue, val, *pccbValue);
2228 *pccbValue = lstrlenW(val);
2229 r = ERROR_MORE_DATA;
2230 }
2231 else
2232 {
2233 lstrcpyW(szValue, val);
2234 *pccbValue = lstrlenW(val);
2235 r = ERROR_SUCCESS;
2236 }
2237
2238 done:
2239 if (view)
2240 {
2241 MSI_ViewClose(view);
2242 msiobj_release(&view->hdr);
2243 if (rec) msiobj_release(&rec->hdr);
2244 }
2245
2246 if (!rec)
2247 {
2248 if (szValue) *szValue = '\0';
2249 if (pccbValue) *pccbValue = 0;
2250 r = ERROR_SUCCESS;
2251 }
2252
2253 return r;
2254 }
2255
2256 UINT WINAPI MsiVerifyPackageA( LPCSTR szPackage )
2257 {
2258 UINT r;
2259 LPWSTR szPack = NULL;
2260
2261 TRACE("%s\n", debugstr_a(szPackage) );
2262
2263 if( szPackage )
2264 {
2265 szPack = strdupAtoW( szPackage );
2266 if( !szPack )
2267 return ERROR_OUTOFMEMORY;
2268 }
2269
2270 r = MsiVerifyPackageW( szPack );
2271
2272 msi_free( szPack );
2273
2274 return r;
2275 }
2276
2277 UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage )
2278 {
2279 MSIHANDLE handle;
2280 UINT r;
2281
2282 TRACE("%s\n", debugstr_w(szPackage) );
2283
2284 r = MsiOpenDatabaseW( szPackage, MSIDBOPEN_READONLY, &handle );
2285 MsiCloseHandle( handle );
2286
2287 return r;
2288 }
2289
2290 static INSTALLSTATE MSI_GetComponentPath(LPCWSTR szProduct, LPCWSTR szComponent,
2291 awstring* lpPathBuf, LPDWORD pcchBuf)
2292 {
2293 WCHAR squished_pc[GUID_SIZE];
2294 WCHAR squished_comp[GUID_SIZE];
2295 HKEY hkey;
2296 LPWSTR path = NULL;
2297 INSTALLSTATE state;
2298 DWORD version;
2299
2300 static const WCHAR wininstaller[] = {
2301 'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
2302
2303 TRACE("%s %s %p %p\n", debugstr_w(szProduct),
2304 debugstr_w(szComponent), lpPathBuf->str.w, pcchBuf);
2305
2306 if (!szProduct || !szComponent)
2307 return INSTALLSTATE_INVALIDARG;
2308
2309 if (lpPathBuf->str.w && !pcchBuf)
2310 return INSTALLSTATE_INVALIDARG;
2311
2312 if (!squash_guid(szProduct, squished_pc) ||
2313 !squash_guid(szComponent, squished_comp))
2314 return INSTALLSTATE_INVALIDARG;
2315
2316 state = INSTALLSTATE_UNKNOWN;
2317
2318 if (MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &hkey, FALSE) == ERROR_SUCCESS ||
2319 MSIREG_OpenUserDataComponentKey(szComponent, NULL, &hkey, FALSE) == ERROR_SUCCESS)
2320 {
2321 path = msi_reg_get_val_str(hkey, squished_pc);
2322 RegCloseKey(hkey);
2323
2324 state = INSTALLSTATE_ABSENT;
2325
2326 if ((MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE, NULL,
2327 &hkey, FALSE) == ERROR_SUCCESS ||
2328 MSIREG_OpenUserDataProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
2329 NULL, &hkey, FALSE) == ERROR_SUCCESS) &&
2330 msi_reg_get_val_dword(hkey, wininstaller, &version) &&
2331 GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES)
2332 {
2333 RegCloseKey(hkey);
2334 state = INSTALLSTATE_LOCAL;
2335 }
2336 }
2337
2338 if (state != INSTALLSTATE_LOCAL &&
2339 (MSIREG_OpenProductKey(szProduct, NULL,
2340 MSIINSTALLCONTEXT_USERUNMANAGED,
2341 &hkey, FALSE) == ERROR_SUCCESS ||
2342 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
2343 &hkey, FALSE) == ERROR_SUCCESS))
2344 {
2345 RegCloseKey(hkey);
2346
2347 if (MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &hkey, FALSE) == ERROR_SUCCESS ||
2348 MSIREG_OpenUserDataComponentKey(szComponent, NULL, &hkey, FALSE) == ERROR_SUCCESS)
2349 {
2350 msi_free(path);
2351 path = msi_reg_get_val_str(hkey, squished_pc);
2352 RegCloseKey(hkey);
2353
2354 state = INSTALLSTATE_ABSENT;
2355
2356 if (GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES)
2357 state = INSTALLSTATE_LOCAL;
2358 }
2359 }
2360
2361 if (!path)
2362 return INSTALLSTATE_UNKNOWN;
2363
2364 if (state == INSTALLSTATE_LOCAL && !*path)
2365 state = INSTALLSTATE_NOTUSED;
2366
2367 msi_strcpy_to_awstring(path, lpPathBuf, pcchBuf);
2368 msi_free(path);
2369 return state;
2370 }
2371
2372 /******************************************************************
2373 * MsiGetComponentPathW [MSI.@]
2374 */
2375 INSTALLSTATE WINAPI MsiGetComponentPathW(LPCWSTR szProduct, LPCWSTR szComponent,
2376 LPWSTR lpPathBuf, LPDWORD pcchBuf)
2377 {
2378 awstring path;
2379
2380 path.unicode = TRUE;
2381 path.str.w = lpPathBuf;
2382
2383 return MSI_GetComponentPath( szProduct, szComponent, &path, pcchBuf );
2384 }
2385
2386 /******************************************************************
2387 * MsiGetComponentPathA [MSI.@]
2388 */
2389 INSTALLSTATE WINAPI MsiGetComponentPathA(LPCSTR szProduct, LPCSTR szComponent,
2390 LPSTR lpPathBuf, LPDWORD pcchBuf)
2391 {
2392 LPWSTR szwProduct, szwComponent = NULL;
2393 INSTALLSTATE r = INSTALLSTATE_UNKNOWN;
2394 awstring path;
2395
2396 szwProduct = strdupAtoW( szProduct );
2397 if( szProduct && !szwProduct)
2398 goto end;
2399
2400 szwComponent = strdupAtoW( szComponent );
2401 if( szComponent && !szwComponent )
2402 goto end;
2403
2404 path.unicode = FALSE;
2405 path.str.a = lpPathBuf;
2406
2407 r = MSI_GetComponentPath( szwProduct, szwComponent, &path, pcchBuf );
2408
2409 end:
2410 msi_free( szwProduct );
2411 msi_free( szwComponent );
2412
2413 return r;
2414 }
2415
2416 /******************************************************************
2417 * MsiQueryFeatureStateA [MSI.@]
2418 */
2419 INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature)
2420 {
2421 LPWSTR szwProduct = NULL, szwFeature= NULL;
2422 INSTALLSTATE rc = INSTALLSTATE_UNKNOWN;
2423
2424 szwProduct = strdupAtoW( szProduct );
2425 if ( szProduct && !szwProduct )
2426 goto end;
2427
2428 szwFeature = strdupAtoW( szFeature );
2429 if ( szFeature && !szwFeature )
2430 goto end;
2431
2432 rc = MsiQueryFeatureStateW(szwProduct, szwFeature);
2433
2434 end:
2435 msi_free( szwProduct);
2436 msi_free( szwFeature);
2437
2438 return rc;
2439 }
2440
2441 /******************************************************************
2442 * MsiQueryFeatureStateW [MSI.@]
2443 *
2444 * Checks the state of a feature
2445 *
2446 * PARAMS
2447 * szProduct [I] Product's GUID string
2448 * szFeature [I] Feature's GUID string
2449 *
2450 * RETURNS
2451 * INSTALLSTATE_LOCAL Feature is installed and usable
2452 * INSTALLSTATE_ABSENT Feature is absent
2453 * INSTALLSTATE_ADVERTISED Feature should be installed on demand
2454 * INSTALLSTATE_UNKNOWN An error occurred
2455 * INSTALLSTATE_INVALIDARG One of the GUIDs was invalid
2456 *
2457 */
2458 INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature)
2459 {
2460 WCHAR squishProduct[33], comp[GUID_SIZE];
2461 GUID guid;
2462 LPWSTR components, p, parent_feature, path;
2463 UINT rc;
2464 HKEY hkey;
2465 INSTALLSTATE r;
2466 BOOL missing = FALSE;
2467 BOOL machine = FALSE;
2468 BOOL source = FALSE;
2469
2470 TRACE("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature));
2471
2472 if (!szProduct || !szFeature)
2473 return INSTALLSTATE_INVALIDARG;
2474
2475 if (!squash_guid( szProduct, squishProduct ))
2476 return INSTALLSTATE_INVALIDARG;
2477
2478 if (MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
2479 &hkey, FALSE) != ERROR_SUCCESS &&
2480 MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
2481 &hkey, FALSE) != ERROR_SUCCESS)
2482 {
2483 rc = MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
2484 &hkey, FALSE);
2485 if (rc != ERROR_SUCCESS)
2486 return INSTALLSTATE_UNKNOWN;
2487
2488 machine = TRUE;
2489 }
2490
2491 parent_feature = msi_reg_get_val_str( hkey, szFeature );
2492 RegCloseKey(hkey);
2493
2494 if (!parent_feature)
2495 return INSTALLSTATE_UNKNOWN;
2496
2497 r = (parent_feature[0] == 6) ? INSTALLSTATE_ABSENT : INSTALLSTATE_LOCAL;
2498 msi_free(parent_feature);
2499 if (r == INSTALLSTATE_ABSENT)
2500 return r;
2501
2502 if (machine)
2503 rc = MSIREG_OpenUserDataFeaturesKey(szProduct,
2504 MSIINSTALLCONTEXT_MACHINE,
2505 &hkey, FALSE);
2506 else
2507 rc = MSIREG_OpenUserDataFeaturesKey(szProduct,
2508 MSIINSTALLCONTEXT_USERUNMANAGED,
2509 &hkey, FALSE);
2510
2511 if (rc != ERROR_SUCCESS)
2512 return INSTALLSTATE_ADVERTISED;
2513
2514 components = msi_reg_get_val_str( hkey, szFeature );
2515 RegCloseKey(hkey);
2516
2517 TRACE("rc = %d buffer = %s\n", rc, debugstr_w(components));
2518
2519 if (!components)
2520 return INSTALLSTATE_ADVERTISED;
2521
2522 for( p = components; *p && *p != 2 ; p += 20)
2523 {
2524 if (!decode_base85_guid( p, &guid ))
2525 {
2526 if (p != components)
2527 break;
2528
2529 msi_free(components);
2530 return INSTALLSTATE_BADCONFIG;
2531 }
2532
2533 StringFromGUID2(&guid, comp, GUID_SIZE);
2534
2535 if (machine)
2536 rc = MSIREG_OpenUserDataComponentKey(comp, szLocalSid, &hkey, FALSE);
2537 else
2538 rc = MSIREG_OpenUserDataComponentKey(comp, NULL, &hkey, FALSE);
2539
2540 if (rc != ERROR_SUCCESS)
2541 {
2542 msi_free(components);
2543 return INSTALLSTATE_ADVERTISED;
2544 }
2545
2546 path = msi_reg_get_val_str(hkey, squishProduct);
2547 if (!path)
2548 missing = TRUE;
2549 else if (lstrlenW(path) > 2 &&
2550 path[0] >= '0' && path[0] <= '9' &&
2551 path[1] >= '0' && path[1] <= '9')
2552 {
2553 source = TRUE;
2554 }
2555
2556 msi_free(path);
2557 }
2558
2559 TRACE("%s %s -> %d\n", debugstr_w(szProduct), debugstr_w(szFeature), r);
2560 msi_free(components);
2561
2562 if (missing)
2563 return INSTALLSTATE_ADVERTISED;
2564
2565 if (source)
2566 return INSTALLSTATE_SOURCE;
2567
2568 return INSTALLSTATE_LOCAL;
2569 }
2570
2571 /******************************************************************
2572 * MsiGetFileVersionA [MSI.@]
2573 */
2574 UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf,
2575 LPDWORD pcchVersionBuf, LPSTR lpLangBuf, LPDWORD pcchLangBuf)
2576 {
2577 LPWSTR szwFilePath = NULL, lpwVersionBuff = NULL, lpwLangBuff = NULL;
2578 UINT ret = ERROR_OUTOFMEMORY;
2579
2580 if ((lpVersionBuf && !pcchVersionBuf) ||
2581 (lpLangBuf && !pcchLangBuf))
2582 return ERROR_INVALID_PARAMETER;
2583
2584 if( szFilePath )
2585 {
2586 szwFilePath = strdupAtoW( szFilePath );
2587 if( !szwFilePath )
2588 goto end;
2589 }
2590
2591 if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf )
2592 {
2593 lpwVersionBuff = msi_alloc(*pcchVersionBuf*sizeof(WCHAR));
2594 if( !lpwVersionBuff )
2595 goto end;
2596 }
2597
2598 if( lpLangBuf && pcchLangBuf && *pcchLangBuf )
2599 {
2600 lpwLangBuff = msi_alloc(*pcchLangBuf*sizeof(WCHAR));
2601 if( !lpwLangBuff )
2602 goto end;
2603 }
2604
2605 ret = MsiGetFileVersionW(szwFilePath, lpwVersionBuff, pcchVersionBuf,
2606 lpwLangBuff, pcchLangBuf);
2607
2608 if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwVersionBuff )
2609 WideCharToMultiByte(CP_ACP, 0, lpwVersionBuff, -1,
2610 lpVersionBuf, *pcchVersionBuf + 1, NULL, NULL);
2611 if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwLangBuff )
2612 WideCharToMultiByte(CP_ACP, 0, lpwLangBuff, -1,
2613 lpLangBuf, *pcchLangBuf + 1, NULL, NULL);
2614
2615 end:
2616 msi_free(szwFilePath);
2617 msi_free(lpwVersionBuff);
2618 msi_free(lpwLangBuff);
2619
2620 return ret;
2621 }
2622
2623 /******************************************************************
2624 * MsiGetFileVersionW [MSI.@]
2625 */
2626 UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf,
2627 LPDWORD pcchVersionBuf, LPWSTR lpLangBuf, LPDWORD pcchLangBuf)
2628 {
2629 static const WCHAR szVersionResource[] = {'\\',0};
2630 static const WCHAR szVersionFormat[] = {
2631 '%','d','.','%','d','.','%','d','.','%','d',0};
2632 static const WCHAR szLangResource[] = {
2633 '\\','V','a','r','F','i','l','e','I','n','f','o','\\',
2634 'T','r','a','n','s','l','a','t','i','o','n',0};
2635 static const WCHAR szLangFormat[] = {'%','d',0};
2636 UINT ret = 0;
2637 DWORD dwVerLen, gle;
2638 LPVOID lpVer = NULL;
2639 VS_FIXEDFILEINFO *ffi;
2640 USHORT *lang;
2641 UINT puLen;
2642 WCHAR tmp[32];
2643
2644 TRACE("%s %p %d %p %d\n", debugstr_w(szFilePath),
2645 lpVersionBuf, pcchVersionBuf?*pcchVersionBuf:0,
2646 lpLangBuf, pcchLangBuf?*pcchLangBuf:0);
2647
2648 if ((lpVersionBuf && !pcchVersionBuf) ||
2649 (lpLangBuf && !pcchLangBuf))
2650 return ERROR_INVALID_PARAMETER;
2651
2652 dwVerLen = GetFileVersionInfoSizeW(szFilePath, NULL);
2653 if( !dwVerLen )
2654 {
2655 gle = GetLastError();
2656 if (gle == ERROR_BAD_PATHNAME)
2657 return ERROR_FILE_NOT_FOUND;
2658 else if (gle == ERROR_RESOURCE_DATA_NOT_FOUND)
2659 return ERROR_FILE_INVALID;
2660
2661 return gle;
2662 }
2663
2664 lpVer = msi_alloc(dwVerLen);
2665 if( !lpVer )
2666 {
2667 ret = ERROR_OUTOFMEMORY;
2668 goto end;
2669 }
2670
2671 if( !GetFileVersionInfoW(szFilePath, 0, dwVerLen, lpVer) )
2672 {
2673 ret = GetLastError();
2674 goto end;
2675 }
2676
2677 if (pcchVersionBuf)
2678 {
2679 if( VerQueryValueW(lpVer, szVersionResource, (LPVOID*)&ffi, &puLen) &&
2680 (puLen > 0) )
2681 {
2682 wsprintfW(tmp, szVersionFormat,
2683 HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS),
2684 HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS));
2685 if (lpVersionBuf) lstrcpynW(lpVersionBuf, tmp, *pcchVersionBuf);
2686
2687 if (strlenW(tmp) >= *pcchVersionBuf)
2688 ret = ERROR_MORE_DATA;
2689
2690 *pcchVersionBuf = lstrlenW(tmp);
2691 }
2692 else
2693 {
2694 if (lpVersionBuf) *lpVersionBuf = 0;
2695 *pcchVersionBuf = 0;
2696 }
2697 }
2698
2699 if (pcchLangBuf)
2700 {
2701 if (VerQueryValueW(lpVer, szLangResource, (LPVOID*)&lang, &puLen) &&
2702 (puLen > 0))
2703 {
2704 wsprintfW(tmp, szLangFormat, *lang);
2705 if (lpLangBuf) lstrcpynW(lpLangBuf, tmp, *pcchLangBuf);
2706
2707 if (strlenW(tmp) >= *pcchLangBuf)
2708 ret = ERROR_MORE_DATA;
2709
2710 *pcchLangBuf = lstrlenW(tmp);
2711 }
2712 else
2713 {
2714 if (lpLangBuf) *lpLangBuf = 0;
2715 *pcchLangBuf = 0;
2716 }
2717 }
2718
2719 end:
2720 msi_free(lpVer);
2721 return ret;
2722 }
2723
2724 /***********************************************************************
2725 * MsiGetFeatureUsageW [MSI.@]
2726 */
2727 UINT WINAPI MsiGetFeatureUsageW( LPCWSTR szProduct, LPCWSTR szFeature,
2728 LPDWORD pdwUseCount, LPWORD pwDateUsed )
2729 {
2730 FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szFeature),
2731 pdwUseCount, pwDateUsed);
2732 return ERROR_CALL_NOT_IMPLEMENTED;
2733 }
2734
2735 /***********************************************************************
2736 * MsiGetFeatureUsageA [MSI.@]
2737 */
2738 UINT WINAPI MsiGetFeatureUsageA( LPCSTR szProduct, LPCSTR szFeature,
2739 LPDWORD pdwUseCount, LPWORD pwDateUsed )
2740 {
2741 LPWSTR prod = NULL, feat = NULL;
2742 UINT ret = ERROR_OUTOFMEMORY;
2743
2744 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szFeature),
2745 pdwUseCount, pwDateUsed);
2746
2747 prod = strdupAtoW( szProduct );
2748 if (szProduct && !prod)
2749 goto end;
2750
2751 feat = strdupAtoW( szFeature );
2752 if (szFeature && !feat)
2753 goto end;
2754
2755 ret = MsiGetFeatureUsageW( prod, feat, pdwUseCount, pwDateUsed );
2756
2757 end:
2758 msi_free( prod );
2759 msi_free( feat );
2760
2761 return ret;
2762 }
2763
2764 /***********************************************************************
2765 * MsiUseFeatureExW [MSI.@]
2766 */
2767 INSTALLSTATE WINAPI MsiUseFeatureExW( LPCWSTR szProduct, LPCWSTR szFeature,
2768 DWORD dwInstallMode, DWORD dwReserved )
2769 {
2770 INSTALLSTATE state;
2771
2772 TRACE("%s %s %i %i\n", debugstr_w(szProduct), debugstr_w(szFeature),
2773 dwInstallMode, dwReserved);
2774
2775 state = MsiQueryFeatureStateW( szProduct, szFeature );
2776
2777 if (dwReserved)
2778 return INSTALLSTATE_INVALIDARG;
2779
2780 if (state == INSTALLSTATE_LOCAL && dwInstallMode != INSTALLMODE_NODETECTION)
2781 {
2782 FIXME("mark product %s feature %s as used\n",
2783 debugstr_w(szProduct), debugstr_w(szFeature) );
2784 }
2785
2786 return state;
2787 }
2788
2789 /***********************************************************************
2790 * MsiUseFeatureExA [MSI.@]
2791 */
2792 INSTALLSTATE WINAPI MsiUseFeatureExA( LPCSTR szProduct, LPCSTR szFeature,
2793 DWORD dwInstallMode, DWORD dwReserved )
2794 {
2795 INSTALLSTATE ret = INSTALLSTATE_UNKNOWN;
2796 LPWSTR prod = NULL, feat = NULL;
2797
2798 TRACE("%s %s %i %i\n", debugstr_a(szProduct), debugstr_a(szFeature),
2799 dwInstallMode, dwReserved);
2800
2801 prod = strdupAtoW( szProduct );
2802 if (szProduct && !prod)
2803 goto end;
2804
2805 feat = strdupAtoW( szFeature );
2806 if (szFeature && !feat)
2807 goto end;
2808
2809 ret = MsiUseFeatureExW( prod, feat, dwInstallMode, dwReserved );
2810
2811 end:
2812 msi_free( prod );
2813 msi_free( feat );
2814
2815 return ret;
2816 }
2817
2818 /***********************************************************************
2819 * MsiUseFeatureW [MSI.@]
2820 */
2821 INSTALLSTATE WINAPI MsiUseFeatureW( LPCWSTR szProduct, LPCWSTR szFeature )
2822 {
2823 return MsiUseFeatureExW(szProduct, szFeature, 0, 0);
2824 }
2825
2826 /***********************************************************************
2827 * MsiUseFeatureA [MSI.@]
2828 */
2829 INSTALLSTATE WINAPI MsiUseFeatureA( LPCSTR szProduct, LPCSTR szFeature )
2830 {
2831 return MsiUseFeatureExA(szProduct, szFeature, 0, 0);
2832 }
2833
2834 /***********************************************************************
2835 * MSI_ProvideQualifiedComponentEx [internal]
2836 */
2837 static UINT MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent,
2838 LPCWSTR szQualifier, DWORD dwInstallMode, LPCWSTR szProduct,
2839 DWORD Unused1, DWORD Unused2, awstring *lpPathBuf,
2840 LPDWORD pcchPathBuf)
2841 {
2842 WCHAR product[MAX_FEATURE_CHARS+1], component[MAX_FEATURE_CHARS+1],
2843 feature[MAX_FEATURE_CHARS+1];
2844 LPWSTR info;
2845 HKEY hkey;
2846 DWORD sz;
2847 UINT rc;
2848
2849 TRACE("%s %s %i %s %i %i %p %p\n", debugstr_w(szComponent),
2850 debugstr_w(szQualifier), dwInstallMode, debugstr_w(szProduct),
2851 Unused1, Unused2, lpPathBuf, pcchPathBuf);
2852
2853 rc = MSIREG_OpenUserComponentsKey(szComponent, &hkey, FALSE);
2854 if (rc != ERROR_SUCCESS)
2855 return ERROR_INDEX_ABSENT;
2856
2857 info = msi_reg_get_val_str( hkey, szQualifier );
2858 RegCloseKey(hkey);
2859
2860 if (!info)
2861 return ERROR_INDEX_ABSENT;
2862
2863 MsiDecomposeDescriptorW(info, product, feature, component, &sz);
2864
2865 if (!szProduct)
2866 rc = MSI_GetComponentPath(product, component, lpPathBuf, pcchPathBuf);
2867 else
2868 rc = MSI_GetComponentPath(szProduct, component, lpPathBuf, pcchPathBuf);
2869
2870 msi_free( info );
2871
2872 if (rc != INSTALLSTATE_LOCAL)
2873 return ERROR_FILE_NOT_FOUND;
2874
2875 return ERROR_SUCCESS;
2876 }
2877
2878 /***********************************************************************
2879 * MsiProvideQualifiedComponentExW [MSI.@]
2880 */
2881 UINT WINAPI MsiProvideQualifiedComponentExW(LPCWSTR szComponent,
2882 LPCWSTR szQualifier, DWORD dwInstallMode, LPCWSTR szProduct,
2883 DWORD Unused1, DWORD Unused2, LPWSTR lpPathBuf,
2884 LPDWORD pcchPathBuf)
2885 {
2886 awstring path;
2887
2888 path.unicode = TRUE;
2889 path.str.w = lpPathBuf;
2890
2891 return MSI_ProvideQualifiedComponentEx(szComponent, szQualifier,
2892 dwInstallMode, szProduct, Unused1, Unused2, &path, pcchPathBuf);
2893 }
2894
2895 /***********************************************************************
2896 * MsiProvideQualifiedComponentExA [MSI.@]
2897 */
2898 UINT WINAPI MsiProvideQualifiedComponentExA(LPCSTR szComponent,
2899 LPCSTR szQualifier, DWORD dwInstallMode, LPCSTR szProduct,
2900 DWORD Unused1, DWORD Unused2, LPSTR lpPathBuf,
2901 LPDWORD pcchPathBuf)
2902 {
2903 LPWSTR szwComponent, szwQualifier = NULL, szwProduct = NULL;
2904 UINT r = ERROR_OUTOFMEMORY;
2905 awstring path;
2906
2907 TRACE("%s %s %u %s %u %u %p %p\n", debugstr_a(szComponent),
2908 debugstr_a(szQualifier), dwInstallMode, debugstr_a(szProduct),
2909 Unused1, Unused2, lpPathBuf, pcchPathBuf);
2910
2911 szwComponent = strdupAtoW( szComponent );
2912 if (szComponent && !szwComponent)
2913 goto end;
2914
2915 szwQualifier = strdupAtoW( szQualifier );
2916 if (szQualifier && !szwQualifier)
2917 goto end;
2918
2919 szwProduct = strdupAtoW( szProduct );
2920 if (szProduct && !szwProduct)
2921 goto end;
2922
2923 path.unicode = FALSE;
2924 path.str.a = lpPathBuf;
2925
2926 r = MSI_ProvideQualifiedComponentEx(szwComponent, szwQualifier,
2927 dwInstallMode, szwProduct, Unused1,
2928 Unused2, &path, pcchPathBuf);
2929 end:
2930 msi_free(szwProduct);
2931 msi_free(szwComponent);
2932 msi_free(szwQualifier);
2933
2934 return r;
2935 }
2936
2937 /***********************************************************************
2938 * MsiProvideQualifiedComponentW [MSI.@]
2939 */
2940 UINT WINAPI MsiProvideQualifiedComponentW( LPCWSTR szComponent,
2941 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR lpPathBuf,
2942 LPDWORD pcchPathBuf)
2943 {
2944 return MsiProvideQualifiedComponentExW(szComponent, szQualifier,
2945 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
2946 }
2947
2948 /***********************************************************************
2949 * MsiProvideQualifiedComponentA [MSI.@]
2950 */
2951 UINT WINAPI MsiProvideQualifiedComponentA( LPCSTR szComponent,
2952 LPCSTR szQualifier, DWORD dwInstallMode, LPSTR lpPathBuf,
2953 LPDWORD pcchPathBuf)
2954 {
2955 return MsiProvideQualifiedComponentExA(szComponent, szQualifier,
2956 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
2957 }
2958
2959 /***********************************************************************
2960 * MSI_GetUserInfo [internal]
2961 */
2962 static USERINFOSTATE MSI_GetUserInfo(LPCWSTR szProduct,
2963 awstring *lpUserNameBuf, LPDWORD pcchUserNameBuf,
2964 awstring *lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
2965 awstring *lpSerialBuf, LPDWORD pcchSerialBuf)
2966 {
2967 WCHAR squished_pc[SQUISH_GUID_SIZE];
2968 LPWSTR user, org, serial;
2969 USERINFOSTATE state;
2970 HKEY hkey, props;
2971 LPCWSTR orgptr;
2972 UINT r;
2973
2974 static const WCHAR szEmpty[] = {0};
2975
2976 TRACE("%s %p %p %p %p %p %p\n", debugstr_w(szProduct), lpUserNameBuf,
2977 pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf,
2978 pcchSerialBuf);
2979
2980 if (!szProduct || !squash_guid(szProduct, squished_pc))
2981 return USERINFOSTATE_INVALIDARG;
2982
2983 if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
2984 &hkey, FALSE) != ERROR_SUCCESS &&
2985 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2986 &hkey, FALSE) != ERROR_SUCCESS &&
2987 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
2988 &hkey, FALSE) != ERROR_SUCCESS)
2989 {
2990 return USERINFOSTATE_UNKNOWN;
2991 }
2992
2993 if (MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
2994 NULL, &props, FALSE) != ERROR_SUCCESS &&
2995 MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE,
2996 NULL, &props, FALSE) != ERROR_SUCCESS)
2997 {
2998 RegCloseKey(hkey);
2999 return USERINFOSTATE_ABSENT;
3000 }
3001
3002 user = msi_reg_get_val_str(props, INSTALLPROPERTY_REGOWNERW);
3003 org = msi_reg_get_val_str(props, INSTALLPROPERTY_REGCOMPANYW);
3004 serial = msi_reg_get_val_str(props, INSTALLPROPERTY_PRODUCTIDW);
3005 state = USERINFOSTATE_ABSENT;
3006
3007 RegCloseKey(hkey);
3008 RegCloseKey(props);
3009
3010 if (user && serial)
3011 state = USERINFOSTATE_PRESENT;
3012
3013 if (pcchUserNameBuf)
3014 {
3015 if (lpUserNameBuf && !user)
3016 {
3017 (*pcchUserNameBuf)--;
3018 goto done;
3019 }
3020
3021 r = msi_strcpy_to_awstring(user, lpUserNameBuf, pcchUserNameBuf);
3022 if (r == ERROR_MORE_DATA)
3023 {
3024 state = USERINFOSTATE_MOREDATA;
3025 goto done;
3026 }
3027 }
3028
3029 if (pcchOrgNameBuf)
3030 {
3031 orgptr = org;
3032 if (!orgptr) orgptr = szEmpty;
3033
3034 r = msi_strcpy_to_awstring(orgptr, lpOrgNameBuf, pcchOrgNameBuf);
3035 if (r == ERROR_MORE_DATA)
3036 {
3037 state = USERINFOSTATE_MOREDATA;
3038 goto done;
3039 }
3040 }
3041
3042 if (pcchSerialBuf)
3043 {
3044 if (!serial)
3045 {
3046 (*pcchSerialBuf)--;
3047 goto done;
3048 }
3049
3050 r = msi_strcpy_to_awstring(serial, lpSerialBuf, pcchSerialBuf);
3051 if (r == ERROR_MORE_DATA)
3052 state = USERINFOSTATE_MOREDATA;
3053 }
3054
3055 done:
3056 msi_free(user);
3057 msi_free(org);
3058 msi_free(serial);
3059
3060 return state;
3061 }
3062
3063 /***********************************************************************
3064 * MsiGetUserInfoW [MSI.@]
3065 */
3066 USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct,
3067 LPWSTR lpUserNameBuf, LPDWORD pcchUserNameBuf,
3068 LPWSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
3069 LPWSTR lpSerialBuf, LPDWORD pcchSerialBuf)
3070 {
3071 awstring user, org, serial;
3072
3073 if ((lpUserNameBuf && !pcchUserNameBuf) ||
3074 (lpOrgNameBuf && !pcchOrgNameBuf) ||
3075 (lpSerialBuf && !pcchSerialBuf))
3076 return USERINFOSTATE_INVALIDARG;
3077
3078 user.unicode = TRUE;
3079 user.str.w = lpUserNameBuf;
3080 org.unicode = TRUE;
3081 org.str.w = lpOrgNameBuf;
3082 serial.unicode = TRUE;
3083 serial.str.w = lpSerialBuf;
3084
3085 return MSI_GetUserInfo( szProduct, &user, pcchUserNameBuf,
3086 &org, pcchOrgNameBuf,
3087 &serial, pcchSerialBuf );
3088 }
3089
3090 USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR szProduct,
3091 LPSTR lpUserNameBuf, LPDWORD pcchUserNameBuf,
3092 LPSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
3093 LPSTR lpSerialBuf, LPDWORD pcchSerialBuf)
3094 {
3095 awstring user, org, serial;
3096 LPWSTR prod;
3097 UINT r;
3098
3099 if ((lpUserNameBuf && !pcchUserNameBuf) ||
3100 (lpOrgNameBuf && !pcchOrgNameBuf) ||
3101 (lpSerialBuf && !pcchSerialBuf))
3102 return USERINFOSTATE_INVALIDARG;
3103
3104 prod = strdupAtoW( szProduct );
3105 if (szProduct && !prod)
3106 return ERROR_OUTOFMEMORY;
3107
3108 user.unicode = FALSE;
3109 user.str.a = lpUserNameBuf;
3110 org.unicode = FALSE;
3111 org.str.a = lpOrgNameBuf;
3112 serial.unicode = FALSE;
3113 serial.str.a = lpSerialBuf;
3114
3115 r = MSI_GetUserInfo( prod, &user, pcchUserNameBuf,
3116 &org, pcchOrgNameBuf,
3117 &serial, pcchSerialBuf );
3118
3119 msi_free( prod );
3120
3121 return r;
3122 }
3123
3124 UINT WINAPI MsiCollectUserInfoW(LPCWSTR szProduct)
3125 {
3126 MSIHANDLE handle;
3127 UINT rc;
3128 MSIPACKAGE *package;
3129 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
3130
3131 TRACE("(%s)\n",debugstr_w(szProduct));
3132
3133 rc = MsiOpenProductW(szProduct,&handle);
3134 if (rc != ERROR_SUCCESS)
3135 return ERROR_INVALID_PARAMETER;
3136
3137 /* MsiCollectUserInfo cannot be called from a custom action. */
3138 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
3139 if (!package)
3140 return ERROR_CALL_NOT_IMPLEMENTED;
3141
3142 rc = ACTION_PerformUIAction(package, szFirstRun, -1);
3143 msiobj_release( &package->hdr );
3144
3145 MsiCloseHandle(handle);
3146
3147 return rc;
3148 }
3149
3150 UINT WINAPI MsiCollectUserInfoA(LPCSTR szProduct)
3151 {
3152 MSIHANDLE handle;
3153 UINT rc;
3154 MSIPACKAGE *package;
3155 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
3156
3157 TRACE("(%s)\n",debugstr_a(szProduct));
3158
3159 rc = MsiOpenProductA(szProduct,&handle);
3160 if (rc != ERROR_SUCCESS)
3161 return ERROR_INVALID_PARAMETER;
3162
3163 /* MsiCollectUserInfo cannot be called from a custom action. */
3164 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
3165 if (!package)
3166 return ERROR_CALL_NOT_IMPLEMENTED;
3167
3168 rc = ACTION_PerformUIAction(package, szFirstRun, -1);
3169 msiobj_release( &package->hdr );
3170
3171 MsiCloseHandle(handle);
3172
3173 return rc;
3174 }
3175
3176 /***********************************************************************
3177 * MsiConfigureFeatureA [MSI.@]
3178 */
3179 UINT WINAPI MsiConfigureFeatureA(LPCSTR szProduct, LPCSTR szFeature, INSTALLSTATE eInstallState)
3180 {
3181 LPWSTR prod, feat = NULL;
3182 UINT r = ERROR_OUTOFMEMORY;
3183
3184 TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature), eInstallState);
3185
3186 prod = strdupAtoW( szProduct );
3187 if (szProduct && !prod)
3188 goto end;
3189
3190 feat = strdupAtoW( szFeature );
3191 if (szFeature && !feat)
3192 goto end;
3193
3194 r = MsiConfigureFeatureW(prod, feat, eInstallState);
3195
3196 end:
3197 msi_free(feat);
3198 msi_free(prod);
3199
3200 return r;
3201 }
3202
3203 /***********************************************************************
3204 * MsiConfigureFeatureW [MSI.@]
3205 */
3206 UINT WINAPI MsiConfigureFeatureW(LPCWSTR szProduct, LPCWSTR szFeature, INSTALLSTATE eInstallState)
3207 {
3208 static const WCHAR szCostInit[] = { 'C','o','s','t','I','n','i','t','i','a','l','i','z','e',0 };
3209 MSIPACKAGE *package = NULL;
3210 UINT r;
3211 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH];
3212 DWORD sz;
3213
3214 TRACE("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature), eInstallState);
3215
3216 if (!szProduct || !szFeature)
3217 return ERROR_INVALID_PARAMETER;
3218
3219 switch (eInstallState)
3220 {
3221 case INSTALLSTATE_DEFAULT:
3222 /* FIXME: how do we figure out the default location? */
3223 eInstallState = INSTALLSTATE_LOCAL;
3224 break;
3225 case INSTALLSTATE_LOCAL:
3226 case INSTALLSTATE_SOURCE:
3227 case INSTALLSTATE_ABSENT:
3228 case INSTALLSTATE_ADVERTISED: