sync msi with wine 1.1.22
[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 UINT WINAPI MsiDetermineApplicablePatchesW(LPCWSTR szProductPackagePath,
493 DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOW pPatchInfo)
494 {
495 FIXME("(%s, %d, %p): stub!\n", debugstr_w(szProductPackagePath),
496 cPatchInfo, pPatchInfo);
497
498 return ERROR_CALL_NOT_IMPLEMENTED;
499 }
500
501 UINT WINAPI MsiDeterminePatchSequenceA(LPCSTR szProductCode, LPCSTR szUserSid,
502 MSIINSTALLCONTEXT dwContext, DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOA pPatchInfo)
503 {
504 FIXME("(%s, %s, %d, %d, %p): stub!\n", debugstr_a(szProductCode),
505 debugstr_a(szUserSid), dwContext, cPatchInfo, pPatchInfo);
506
507 return ERROR_CALL_NOT_IMPLEMENTED;
508 }
509
510 UINT WINAPI MsiDeterminePatchSequenceW(LPCWSTR szProductCode, LPCWSTR szUserSid,
511 MSIINSTALLCONTEXT dwContext, DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOW pPatchInfo)
512 {
513 FIXME("(%s, %s, %d, %d, %p): stub!\n", debugstr_w(szProductCode),
514 debugstr_w(szUserSid), dwContext, cPatchInfo, pPatchInfo);
515
516 return ERROR_CALL_NOT_IMPLEMENTED;
517 }
518
519 static UINT msi_open_package(LPCWSTR product, MSIINSTALLCONTEXT context,
520 MSIPACKAGE **package)
521 {
522 UINT r;
523 DWORD sz;
524 HKEY props;
525 LPWSTR localpack;
526 WCHAR sourcepath[MAX_PATH];
527 WCHAR filename[MAX_PATH];
528
529 static const WCHAR szLocalPackage[] = {
530 'L','o','c','a','l','P','a','c','k','a','g','e',0};
531
532
533 r = MSIREG_OpenInstallProps(product, context, NULL, &props, FALSE);
534 if (r != ERROR_SUCCESS)
535 return ERROR_BAD_CONFIGURATION;
536
537 localpack = msi_reg_get_val_str(props, szLocalPackage);
538 if (localpack)
539 {
540 lstrcpyW(sourcepath, localpack);
541 msi_free(localpack);
542 }
543
544 if (!localpack || GetFileAttributesW(sourcepath) == INVALID_FILE_ATTRIBUTES)
545 {
546 sz = sizeof(sourcepath);
547 MsiSourceListGetInfoW(product, NULL, context, MSICODE_PRODUCT,
548 INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
549
550 sz = sizeof(filename);
551 MsiSourceListGetInfoW(product, NULL, context, MSICODE_PRODUCT,
552 INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
553
554 lstrcatW(sourcepath, filename);
555 }
556
557 if (GetFileAttributesW(sourcepath) == INVALID_FILE_ATTRIBUTES)
558 return ERROR_INSTALL_SOURCE_ABSENT;
559
560 return MSI_OpenPackageW(sourcepath, package);
561 }
562
563 UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
564 INSTALLSTATE eInstallState, LPCWSTR szCommandLine)
565 {
566 MSIPACKAGE* package = NULL;
567 MSIINSTALLCONTEXT context;
568 UINT r;
569 DWORD sz;
570 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH];
571 LPWSTR commandline;
572
573 static const WCHAR szInstalled[] = {
574 ' ','I','n','s','t','a','l','l','e','d','=','1',0};
575 static const WCHAR szRemoveAll[] = {
576 ' ','R','E','M','O','V','E','=','A','L','L',0};
577 static const WCHAR szMachine[] = {
578 ' ','A','L','L','U','S','E','R','S','=','1',0};
579
580 TRACE("%s %d %d %s\n",debugstr_w(szProduct), iInstallLevel, eInstallState,
581 debugstr_w(szCommandLine));
582
583 if (!szProduct || lstrlenW(szProduct) != GUID_SIZE - 1)
584 return ERROR_INVALID_PARAMETER;
585
586 if (eInstallState == INSTALLSTATE_ADVERTISED ||
587 eInstallState == INSTALLSTATE_SOURCE)
588 {
589 FIXME("State %d not implemented\n", eInstallState);
590 return ERROR_CALL_NOT_IMPLEMENTED;
591 }
592
593 r = msi_locate_product(szProduct, &context);
594 if (r != ERROR_SUCCESS)
595 return r;
596
597 r = msi_open_package(szProduct, context, &package);
598 if (r != ERROR_SUCCESS)
599 return r;
600
601 sz = lstrlenW(szInstalled) + 1;
602
603 if (szCommandLine)
604 sz += lstrlenW(szCommandLine);
605
606 if (eInstallState == INSTALLSTATE_ABSENT)
607 sz += lstrlenW(szRemoveAll);
608
609 if (context == MSIINSTALLCONTEXT_MACHINE)
610 sz += lstrlenW(szMachine);
611
612 commandline = msi_alloc(sz * sizeof(WCHAR));
613 if (!commandline)
614 {
615 r = ERROR_OUTOFMEMORY;
616 goto end;
617 }
618
619 commandline[0] = 0;
620 if (szCommandLine)
621 lstrcpyW(commandline,szCommandLine);
622
623 if (MsiQueryProductStateW(szProduct) != INSTALLSTATE_UNKNOWN)
624 lstrcatW(commandline,szInstalled);
625
626 if (eInstallState == INSTALLSTATE_ABSENT)
627 lstrcatW(commandline, szRemoveAll);
628
629 if (context == MSIINSTALLCONTEXT_MACHINE)
630 lstrcatW(commandline, szMachine);
631
632 sz = sizeof(sourcepath);
633 MsiSourceListGetInfoW(szProduct, NULL, context, MSICODE_PRODUCT,
634 INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
635
636 sz = sizeof(filename);
637 MsiSourceListGetInfoW(szProduct, NULL, context, MSICODE_PRODUCT,
638 INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
639
640 strcatW(sourcepath, filename);
641
642 r = MSI_InstallPackage( package, sourcepath, commandline );
643
644 msi_free(commandline);
645
646 end:
647 msiobj_release( &package->hdr );
648
649 return r;
650 }
651
652 UINT WINAPI MsiConfigureProductExA(LPCSTR szProduct, int iInstallLevel,
653 INSTALLSTATE eInstallState, LPCSTR szCommandLine)
654 {
655 LPWSTR szwProduct = NULL;
656 LPWSTR szwCommandLine = NULL;
657 UINT r = ERROR_OUTOFMEMORY;
658
659 if( szProduct )
660 {
661 szwProduct = strdupAtoW( szProduct );
662 if( !szwProduct )
663 goto end;
664 }
665
666 if( szCommandLine)
667 {
668 szwCommandLine = strdupAtoW( szCommandLine );
669 if( !szwCommandLine)
670 goto end;
671 }
672
673 r = MsiConfigureProductExW( szwProduct, iInstallLevel, eInstallState,
674 szwCommandLine );
675 end:
676 msi_free( szwProduct );
677 msi_free( szwCommandLine);
678
679 return r;
680 }
681
682 UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel,
683 INSTALLSTATE eInstallState)
684 {
685 LPWSTR szwProduct = NULL;
686 UINT r;
687
688 TRACE("%s %d %d\n",debugstr_a(szProduct), iInstallLevel, eInstallState);
689
690 if( szProduct )
691 {
692 szwProduct = strdupAtoW( szProduct );
693 if( !szwProduct )
694 return ERROR_OUTOFMEMORY;
695 }
696
697 r = MsiConfigureProductW( szwProduct, iInstallLevel, eInstallState );
698 msi_free( szwProduct );
699
700 return r;
701 }
702
703 UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel,
704 INSTALLSTATE eInstallState)
705 {
706 return MsiConfigureProductExW(szProduct, iInstallLevel, eInstallState, NULL);
707 }
708
709 UINT WINAPI MsiGetProductCodeA(LPCSTR szComponent, LPSTR szBuffer)
710 {
711 LPWSTR szwComponent = NULL;
712 UINT r;
713 WCHAR szwBuffer[GUID_SIZE];
714
715 TRACE("%s %s\n",debugstr_a(szComponent), debugstr_a(szBuffer));
716
717 if( szComponent )
718 {
719 szwComponent = strdupAtoW( szComponent );
720 if( !szwComponent )
721 return ERROR_OUTOFMEMORY;
722 }
723
724 *szwBuffer = '\0';
725 r = MsiGetProductCodeW( szwComponent, szwBuffer );
726
727 if(*szwBuffer)
728 WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, GUID_SIZE, NULL, NULL);
729
730 msi_free( szwComponent );
731
732 return r;
733 }
734
735 UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer)
736 {
737 UINT rc, index;
738 HKEY compkey, prodkey;
739 WCHAR squished_comp[GUID_SIZE];
740 WCHAR squished_prod[GUID_SIZE];
741 DWORD sz = GUID_SIZE;
742
743 TRACE("%s %p\n", debugstr_w(szComponent), szBuffer);
744
745 if (!szComponent || !*szComponent)
746 return ERROR_INVALID_PARAMETER;
747
748 if (!squash_guid(szComponent, squished_comp))
749 return ERROR_INVALID_PARAMETER;
750
751 if (MSIREG_OpenUserDataComponentKey(szComponent, NULL, &compkey, FALSE) != ERROR_SUCCESS &&
752 MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &compkey, FALSE) != ERROR_SUCCESS)
753 {
754 return ERROR_UNKNOWN_COMPONENT;
755 }
756
757 rc = RegEnumValueW(compkey, 0, squished_prod, &sz, NULL, NULL, NULL, NULL);
758 if (rc != ERROR_SUCCESS)
759 {
760 RegCloseKey(compkey);
761 return ERROR_UNKNOWN_COMPONENT;
762 }
763
764 /* check simple case, only one product */
765 rc = RegEnumValueW(compkey, 1, squished_prod, &sz, NULL, NULL, NULL, NULL);
766 if (rc == ERROR_NO_MORE_ITEMS)
767 {
768 rc = ERROR_SUCCESS;
769 goto done;
770 }
771
772 index = 0;
773 while ((rc = RegEnumValueW(compkey, index, squished_prod, &sz,
774 NULL, NULL, NULL, NULL)) != ERROR_NO_MORE_ITEMS)
775 {
776 index++;
777 sz = GUID_SIZE;
778 unsquash_guid(squished_prod, szBuffer);
779
780 if (MSIREG_OpenProductKey(szBuffer, NULL,
781 MSIINSTALLCONTEXT_USERMANAGED,
782 &prodkey, FALSE) == ERROR_SUCCESS ||
783 MSIREG_OpenProductKey(szBuffer, NULL,
784 MSIINSTALLCONTEXT_USERUNMANAGED,
785 &prodkey, FALSE) == ERROR_SUCCESS ||
786 MSIREG_OpenProductKey(szBuffer, NULL,
787 MSIINSTALLCONTEXT_MACHINE,
788 &prodkey, FALSE) == ERROR_SUCCESS)
789 {
790 RegCloseKey(prodkey);
791 rc = ERROR_SUCCESS;
792 goto done;
793 }
794 }
795
796 rc = ERROR_INSTALL_FAILURE;
797
798 done:
799 RegCloseKey(compkey);
800 unsquash_guid(squished_prod, szBuffer);
801 return rc;
802 }
803
804 static LPWSTR msi_reg_get_value(HKEY hkey, LPCWSTR name, DWORD *type)
805 {
806 DWORD dval;
807 LONG res;
808 WCHAR temp[20];
809
810 static const WCHAR format[] = {'%','d',0};
811
812 res = RegQueryValueExW(hkey, name, NULL, type, NULL, NULL);
813 if (res != ERROR_SUCCESS)
814 return NULL;
815
816 if (*type == REG_SZ)
817 return msi_reg_get_val_str(hkey, name);
818
819 if (!msi_reg_get_val_dword(hkey, name, &dval))
820 return NULL;
821
822 sprintfW(temp, format, dval);
823 return strdupW(temp);
824 }
825
826 static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
827 awstring *szValue, LPDWORD pcchValueBuf)
828 {
829 MSIINSTALLCONTEXT context = MSIINSTALLCONTEXT_USERUNMANAGED;
830 UINT r = ERROR_UNKNOWN_PROPERTY;
831 HKEY prodkey, userdata, source;
832 LPWSTR val = NULL;
833 WCHAR squished_pc[GUID_SIZE];
834 WCHAR packagecode[GUID_SIZE];
835 BOOL badconfig = FALSE;
836 LONG res;
837 DWORD save, type = REG_NONE;
838
839 static WCHAR empty[] = {0};
840 static const WCHAR sourcelist[] = {
841 'S','o','u','r','c','e','L','i','s','t',0};
842 static const WCHAR display_name[] = {
843 'D','i','s','p','l','a','y','N','a','m','e',0};
844 static const WCHAR display_version[] = {
845 'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
846 static const WCHAR assignment[] = {
847 'A','s','s','i','g','n','m','e','n','t',0};
848
849 TRACE("%s %s %p %p\n", debugstr_w(szProduct),
850 debugstr_w(szAttribute), szValue, pcchValueBuf);
851
852 if ((szValue->str.w && !pcchValueBuf) || !szProduct || !szAttribute)
853 return ERROR_INVALID_PARAMETER;
854
855 if (!squash_guid(szProduct, squished_pc))
856 return ERROR_INVALID_PARAMETER;
857
858 if ((r = MSIREG_OpenProductKey(szProduct, NULL,
859 MSIINSTALLCONTEXT_USERMANAGED,
860 &prodkey, FALSE)) != ERROR_SUCCESS &&
861 (r = MSIREG_OpenProductKey(szProduct, NULL,
862 MSIINSTALLCONTEXT_USERUNMANAGED,
863 &prodkey, FALSE)) != ERROR_SUCCESS &&
864 (r = MSIREG_OpenProductKey(szProduct, NULL,
865 MSIINSTALLCONTEXT_MACHINE,
866 &prodkey, FALSE)) == ERROR_SUCCESS)
867 {
868 context = MSIINSTALLCONTEXT_MACHINE;
869 }
870
871 MSIREG_OpenInstallProps(szProduct, context, NULL, &userdata, FALSE);
872
873 if (!lstrcmpW(szAttribute, INSTALLPROPERTY_HELPLINKW) ||
874 !lstrcmpW(szAttribute, INSTALLPROPERTY_HELPTELEPHONEW) ||
875 !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLDATEW) ||
876 !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW) ||
877 !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLLOCATIONW) ||
878 !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLSOURCEW) ||
879 !lstrcmpW(szAttribute, INSTALLPROPERTY_LOCALPACKAGEW) ||
880 !lstrcmpW(szAttribute, INSTALLPROPERTY_PUBLISHERW) ||
881 !lstrcmpW(szAttribute, INSTALLPROPERTY_URLINFOABOUTW) ||
882 !lstrcmpW(szAttribute, INSTALLPROPERTY_URLUPDATEINFOW) ||
883 !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONMINORW) ||
884 !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONMAJORW) ||
885 !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW) ||
886 !lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTIDW) ||
887 !lstrcmpW(szAttribute, INSTALLPROPERTY_REGCOMPANYW) ||
888 !lstrcmpW(szAttribute, INSTALLPROPERTY_REGOWNERW))
889 {
890 if (!prodkey)
891 {
892 r = ERROR_UNKNOWN_PRODUCT;
893 goto done;
894 }
895
896 if (!userdata)
897 return ERROR_UNKNOWN_PROPERTY;
898
899 if (!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW))
900 szAttribute = display_name;
901 else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW))
902 szAttribute = display_version;
903
904 val = msi_reg_get_value(userdata, szAttribute, &type);
905 if (!val)
906 val = empty;
907 }
908 else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTANCETYPEW) ||
909 !lstrcmpW(szAttribute, INSTALLPROPERTY_TRANSFORMSW) ||
910 !lstrcmpW(szAttribute, INSTALLPROPERTY_LANGUAGEW) ||
911 !lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTNAMEW) ||
912 !lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW) ||
913 !lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW) ||
914 !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONW) ||
915 !lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTICONW) ||
916 !lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGENAMEW) ||
917 !lstrcmpW(szAttribute, INSTALLPROPERTY_AUTHORIZED_LUA_APPW))
918 {
919 if (!prodkey)
920 {
921 r = ERROR_UNKNOWN_PRODUCT;
922 goto done;
923 }
924
925 if (!lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW))
926 szAttribute = assignment;
927
928 if (!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGENAMEW))
929 {
930 res = RegOpenKeyW(prodkey, sourcelist, &source);
931 if (res != ERROR_SUCCESS)
932 {
933 r = ERROR_UNKNOWN_PRODUCT;
934 goto done;
935 }
936
937 val = msi_reg_get_value(source, szAttribute, &type);
938 if (!val)
939 val = empty;
940
941 RegCloseKey(source);
942 }
943 else
944 {
945 val = msi_reg_get_value(prodkey, szAttribute, &type);
946 if (!val)
947 val = empty;
948 }
949
950 if (val != empty && type != REG_DWORD &&
951 !lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW))
952 {
953 if (lstrlenW(val) != SQUISH_GUID_SIZE - 1)
954 badconfig = TRUE;
955 else
956 {
957 unsquash_guid(val, packagecode);
958 msi_free(val);
959 val = strdupW(packagecode);
960 }
961 }
962 }
963
964 if (!val)
965 {
966 r = ERROR_UNKNOWN_PROPERTY;
967 goto done;
968 }
969
970 if (pcchValueBuf)
971 {
972 save = *pcchValueBuf;
973
974 if (strlenW(val) < *pcchValueBuf)
975 r = msi_strcpy_to_awstring(val, szValue, pcchValueBuf);
976 else if (szValue->str.a || szValue->str.w)
977 r = ERROR_MORE_DATA;
978
979 if (!badconfig)
980 *pcchValueBuf = lstrlenW(val);
981 else if (r == ERROR_SUCCESS)
982 {
983 *pcchValueBuf = save;
984 r = ERROR_BAD_CONFIGURATION;
985 }
986 }
987 else if (badconfig)
988 r = ERROR_BAD_CONFIGURATION;
989
990 if (val != empty)
991 msi_free(val);
992
993 done:
994 RegCloseKey(prodkey);
995 RegCloseKey(userdata);
996 return r;
997 }
998
999 UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute,
1000 LPSTR szBuffer, LPDWORD pcchValueBuf)
1001 {
1002 LPWSTR szwProduct, szwAttribute = NULL;
1003 UINT r = ERROR_OUTOFMEMORY;
1004 awstring buffer;
1005
1006 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szAttribute),
1007 szBuffer, pcchValueBuf);
1008
1009 szwProduct = strdupAtoW( szProduct );
1010 if( szProduct && !szwProduct )
1011 goto end;
1012
1013 szwAttribute = strdupAtoW( szAttribute );
1014 if( szAttribute && !szwAttribute )
1015 goto end;
1016
1017 buffer.unicode = FALSE;
1018 buffer.str.a = szBuffer;
1019
1020 r = MSI_GetProductInfo( szwProduct, szwAttribute,
1021 &buffer, pcchValueBuf );
1022
1023 end:
1024 msi_free( szwProduct );
1025 msi_free( szwAttribute );
1026
1027 return r;
1028 }
1029
1030 UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute,
1031 LPWSTR szBuffer, LPDWORD pcchValueBuf)
1032 {
1033 awstring buffer;
1034
1035 TRACE("%s %s %p %p\n", debugstr_w(szProduct), debugstr_w(szAttribute),
1036 szBuffer, pcchValueBuf);
1037
1038 buffer.unicode = TRUE;
1039 buffer.str.w = szBuffer;
1040
1041 return MSI_GetProductInfo( szProduct, szAttribute,
1042 &buffer, pcchValueBuf );
1043 }
1044
1045 UINT WINAPI MsiGetProductInfoExA(LPCSTR szProductCode, LPCSTR szUserSid,
1046 MSIINSTALLCONTEXT dwContext, LPCSTR szProperty,
1047 LPSTR szValue, LPDWORD pcchValue)
1048 {
1049 LPWSTR product = NULL;
1050 LPWSTR usersid = NULL;
1051 LPWSTR property = NULL;
1052 LPWSTR value = NULL;
1053 DWORD len = 0;
1054 UINT r;
1055
1056 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_a(szProductCode),
1057 debugstr_a(szUserSid), dwContext, debugstr_a(szProperty),
1058 szValue, pcchValue);
1059
1060 if (szValue && !pcchValue)
1061 return ERROR_INVALID_PARAMETER;
1062
1063 if (szProductCode) product = strdupAtoW(szProductCode);
1064 if (szUserSid) usersid = strdupAtoW(szUserSid);
1065 if (szProperty) property = strdupAtoW(szProperty);
1066
1067 r = MsiGetProductInfoExW(product, usersid, dwContext, property,
1068 NULL, &len);
1069 if (r != ERROR_SUCCESS)
1070 goto done;
1071
1072 value = msi_alloc(++len * sizeof(WCHAR));
1073 if (!value)
1074 {
1075 r = ERROR_OUTOFMEMORY;
1076 goto done;
1077 }
1078
1079 r = MsiGetProductInfoExW(product, usersid, dwContext, property,
1080 value, &len);
1081 if (r != ERROR_SUCCESS)
1082 goto done;
1083
1084 if (!pcchValue)
1085 goto done;
1086
1087 len = WideCharToMultiByte(CP_ACP, 0, value, -1, NULL, 0, NULL, NULL);
1088 if (*pcchValue >= len)
1089 WideCharToMultiByte(CP_ACP, 0, value, -1, szValue, len, NULL, NULL);
1090 else if (szValue)
1091 {
1092 r = ERROR_MORE_DATA;
1093 if (*pcchValue > 0)
1094 *szValue = '\0';
1095 }
1096
1097 if (*pcchValue <= len || !szValue)
1098 len = len * sizeof(WCHAR) - 1;
1099
1100 *pcchValue = len - 1;
1101
1102 done:
1103 msi_free(product);
1104 msi_free(usersid);
1105 msi_free(property);
1106 msi_free(value);
1107
1108 return r;
1109 }
1110
1111 static UINT msi_copy_outval(LPWSTR val, LPWSTR out, LPDWORD size)
1112 {
1113 UINT r;
1114
1115 if (!val)
1116 return ERROR_UNKNOWN_PROPERTY;
1117
1118 if (out)
1119 {
1120 if (strlenW(val) >= *size)
1121 {
1122 r = ERROR_MORE_DATA;
1123 if (*size > 0)
1124 *out = '\0';
1125 }
1126 else
1127 lstrcpyW(out, val);
1128 }
1129
1130 if (size)
1131 *size = lstrlenW(val);
1132
1133 return ERROR_SUCCESS;
1134 }
1135
1136 UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
1137 MSIINSTALLCONTEXT dwContext, LPCWSTR szProperty,
1138 LPWSTR szValue, LPDWORD pcchValue)
1139 {
1140 WCHAR squished_pc[GUID_SIZE];
1141 LPWSTR val = NULL;
1142 LPCWSTR package = NULL;
1143 HKEY props = NULL, prod;
1144 HKEY classes = NULL, managed;
1145 HKEY hkey = NULL;
1146 DWORD type;
1147 UINT r = ERROR_UNKNOWN_PRODUCT;
1148
1149 static const WCHAR one[] = {'1',0};
1150 static const WCHAR five[] = {'5',0};
1151 static const WCHAR empty[] = {0};
1152 static const WCHAR displayname[] = {
1153 'D','i','s','p','l','a','y','N','a','m','e',0};
1154 static const WCHAR displayversion[] = {
1155 'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
1156 static const WCHAR managed_local_package[] = {
1157 'M','a','n','a','g','e','d','L','o','c','a','l',
1158 'P','a','c','k','a','g','e',0};
1159
1160 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_w(szProductCode),
1161 debugstr_w(szUserSid), dwContext, debugstr_w(szProperty),
1162 szValue, pcchValue);
1163
1164 if (!szProductCode || !squash_guid(szProductCode, squished_pc))
1165 return ERROR_INVALID_PARAMETER;
1166
1167 if (szValue && !pcchValue)
1168 return ERROR_INVALID_PARAMETER;
1169
1170 if (dwContext != MSIINSTALLCONTEXT_USERUNMANAGED &&
1171 dwContext != MSIINSTALLCONTEXT_USERMANAGED &&
1172 dwContext != MSIINSTALLCONTEXT_MACHINE)
1173 return ERROR_INVALID_PARAMETER;
1174
1175 if (!szProperty || !*szProperty)
1176 return ERROR_INVALID_PARAMETER;
1177
1178 if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
1179 return ERROR_INVALID_PARAMETER;
1180
1181 /* FIXME: dwContext is provided, no need to search for it */
1182 MSIREG_OpenProductKey(szProductCode, NULL,MSIINSTALLCONTEXT_USERMANAGED,
1183 &managed, FALSE);
1184 MSIREG_OpenProductKey(szProductCode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1185 &prod, FALSE);
1186
1187 MSIREG_OpenInstallProps(szProductCode, dwContext, NULL, &props, FALSE);
1188
1189 if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
1190 {
1191 package = INSTALLPROPERTY_LOCALPACKAGEW;
1192
1193 if (!props && !prod)
1194 goto done;
1195 }
1196 else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
1197 {
1198 package = managed_local_package;
1199
1200 if (!props && !managed)
1201 goto done;
1202 }
1203 else if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1204 {
1205 package = INSTALLPROPERTY_LOCALPACKAGEW;
1206 MSIREG_OpenProductKey(szProductCode, NULL, dwContext, &classes, FALSE);
1207
1208 if (!props && !classes)
1209 goto done;
1210 }
1211
1212 if (!lstrcmpW(szProperty, INSTALLPROPERTY_HELPLINKW) ||
1213 !lstrcmpW(szProperty, INSTALLPROPERTY_HELPTELEPHONEW) ||
1214 !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLDATEW) ||
1215 !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW) ||
1216 !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLLOCATIONW) ||
1217 !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLSOURCEW) ||
1218 !lstrcmpW(szProperty, INSTALLPROPERTY_LOCALPACKAGEW) ||
1219 !lstrcmpW(szProperty, INSTALLPROPERTY_PUBLISHERW) ||
1220 !lstrcmpW(szProperty, INSTALLPROPERTY_URLINFOABOUTW) ||
1221 !lstrcmpW(szProperty, INSTALLPROPERTY_URLUPDATEINFOW) ||
1222 !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONMINORW) ||
1223 !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONMAJORW) ||
1224 !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONSTRINGW) ||
1225 !lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTIDW) ||
1226 !lstrcmpW(szProperty, INSTALLPROPERTY_REGCOMPANYW) ||
1227 !lstrcmpW(szProperty, INSTALLPROPERTY_REGOWNERW) ||
1228 !lstrcmpW(szProperty, INSTALLPROPERTY_INSTANCETYPEW))
1229 {
1230 val = msi_reg_get_value(props, package, &type);
1231 if (!val)
1232 {
1233 if (prod || classes)
1234 r = ERROR_UNKNOWN_PROPERTY;
1235
1236 goto done;
1237 }
1238
1239 msi_free(val);
1240
1241 if (!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW))
1242 szProperty = displayname;
1243 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONSTRINGW))
1244 szProperty = displayversion;
1245
1246 val = msi_reg_get_value(props, szProperty, &type);
1247 if (!val)
1248 val = strdupW(empty);
1249
1250 r = msi_copy_outval(val, szValue, pcchValue);
1251 }
1252 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_TRANSFORMSW) ||
1253 !lstrcmpW(szProperty, INSTALLPROPERTY_LANGUAGEW) ||
1254 !lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTNAMEW) ||
1255 !lstrcmpW(szProperty, INSTALLPROPERTY_PACKAGECODEW) ||
1256 !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONW) ||
1257 !lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTICONW) ||
1258 !lstrcmpW(szProperty, INSTALLPROPERTY_PACKAGENAMEW) ||
1259 !lstrcmpW(szProperty, INSTALLPROPERTY_AUTHORIZED_LUA_APPW))
1260 {
1261 if (!prod && !classes)
1262 goto done;
1263
1264 if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
1265 hkey = prod;
1266 else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
1267 hkey = managed;
1268 else if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1269 hkey = classes;
1270
1271 val = msi_reg_get_value(hkey, szProperty, &type);
1272 if (!val)
1273 val = strdupW(empty);
1274
1275 r = msi_copy_outval(val, szValue, pcchValue);
1276 }
1277 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTSTATEW))
1278 {
1279 if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1280 {
1281 if (props)
1282 {
1283 val = msi_reg_get_value(props, package, &type);
1284 if (!val)
1285 goto done;
1286
1287 msi_free(val);
1288 val = strdupW(five);
1289 }
1290 else
1291 val = strdupW(one);
1292
1293 r = msi_copy_outval(val, szValue, pcchValue);
1294 goto done;
1295 }
1296 else if (props && (val = msi_reg_get_value(props, package, &type)))
1297 {
1298 msi_free(val);
1299 val = strdupW(five);
1300 r = msi_copy_outval(val, szValue, pcchValue);
1301 goto done;
1302 }
1303
1304 if (prod || managed)
1305 val = strdupW(one);
1306 else
1307 goto done;
1308
1309 r = msi_copy_outval(val, szValue, pcchValue);
1310 }
1311 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_ASSIGNMENTTYPEW))
1312 {
1313 if (!prod && !classes)
1314 goto done;
1315
1316 /* FIXME */
1317 val = strdupW(empty);
1318 r = msi_copy_outval(val, szValue, pcchValue);
1319 }
1320 else
1321 r = ERROR_UNKNOWN_PROPERTY;
1322
1323 done:
1324 RegCloseKey(props);
1325 RegCloseKey(prod);
1326 RegCloseKey(managed);
1327 RegCloseKey(classes);
1328 msi_free(val);
1329
1330 return r;
1331 }
1332
1333 UINT WINAPI MsiGetPatchInfoExA(LPCSTR szPatchCode, LPCSTR szProductCode,
1334 LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1335 LPCSTR szProperty, LPSTR lpValue, DWORD *pcchValue)
1336 {
1337 LPWSTR patch = NULL, product = NULL, usersid = NULL;
1338 LPWSTR property = NULL, val = NULL;
1339 DWORD len;
1340 UINT r;
1341
1342 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_a(szPatchCode),
1343 debugstr_a(szProductCode), debugstr_a(szUserSid), dwContext,
1344 debugstr_a(szProperty), lpValue, pcchValue);
1345
1346 if (lpValue && !pcchValue)
1347 return ERROR_INVALID_PARAMETER;
1348
1349 if (szPatchCode) patch = strdupAtoW(szPatchCode);
1350 if (szProductCode) product = strdupAtoW(szProductCode);
1351 if (szUserSid) usersid = strdupAtoW(szUserSid);
1352 if (szProperty) property = strdupAtoW(szProperty);
1353
1354 len = 0;
1355 r = MsiGetPatchInfoExW(patch, product, usersid, dwContext, property,
1356 NULL, &len);
1357 if (r != ERROR_SUCCESS)
1358 goto done;
1359
1360 val = msi_alloc(++len * sizeof(WCHAR));
1361 if (!val)
1362 {
1363 r = ERROR_OUTOFMEMORY;
1364 goto done;
1365 }
1366
1367 r = MsiGetPatchInfoExW(patch, product, usersid, dwContext, property,
1368 val, &len);
1369 if (r != ERROR_SUCCESS || !pcchValue)
1370 goto done;
1371
1372 if (lpValue)
1373 WideCharToMultiByte(CP_ACP, 0, val, -1, lpValue,
1374 *pcchValue - 1, NULL, NULL);
1375
1376 len = lstrlenW(val);
1377 if ((*val && *pcchValue < len + 1) || !lpValue)
1378 {
1379 if (lpValue)
1380 {
1381 r = ERROR_MORE_DATA;
1382 lpValue[*pcchValue - 1] = '\0';
1383 }
1384
1385 *pcchValue = len * sizeof(WCHAR);
1386 }
1387 else
1388 *pcchValue = len;
1389
1390 done:
1391 msi_free(val);
1392 msi_free(patch);
1393 msi_free(product);
1394 msi_free(usersid);
1395 msi_free(property);
1396
1397 return r;
1398 }
1399
1400 UINT WINAPI MsiGetPatchInfoExW(LPCWSTR szPatchCode, LPCWSTR szProductCode,
1401 LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1402 LPCWSTR szProperty, LPWSTR lpValue, DWORD *pcchValue)
1403 {
1404 WCHAR squished_pc[GUID_SIZE];
1405 WCHAR squished_patch[GUID_SIZE];
1406 HKEY udprod = 0, prod = 0, props = 0;
1407 HKEY patch = 0, patches = 0;
1408 HKEY udpatch = 0, datakey = 0;
1409 HKEY prodpatches = 0;
1410 LPWSTR val = NULL;
1411 UINT r = ERROR_UNKNOWN_PRODUCT;
1412 DWORD len;
1413 LONG res;
1414
1415 static const WCHAR szEmpty[] = {0};
1416 static const WCHAR szPatches[] = {'P','a','t','c','h','e','s',0};
1417 static const WCHAR szInstalled[] = {'I','n','s','t','a','l','l','e','d',0};
1418 static const WCHAR szManagedPackage[] = {'M','a','n','a','g','e','d',
1419 'L','o','c','a','l','P','a','c','k','a','g','e',0};
1420
1421 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_w(szPatchCode),
1422 debugstr_w(szProductCode), debugstr_w(szUserSid), dwContext,
1423 debugstr_w(szProperty), lpValue, pcchValue);
1424
1425 if (!szProductCode || !squash_guid(szProductCode, squished_pc))
1426 return ERROR_INVALID_PARAMETER;
1427
1428 if (!szPatchCode || !squash_guid(szPatchCode, squished_patch))
1429 return ERROR_INVALID_PARAMETER;
1430
1431 if (!szProperty)
1432 return ERROR_INVALID_PARAMETER;
1433
1434 if (lpValue && !pcchValue)
1435 return ERROR_INVALID_PARAMETER;
1436
1437 if (dwContext != MSIINSTALLCONTEXT_USERMANAGED &&
1438 dwContext != MSIINSTALLCONTEXT_USERUNMANAGED &&
1439 dwContext != MSIINSTALLCONTEXT_MACHINE)
1440 return ERROR_INVALID_PARAMETER;
1441
1442 if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
1443 return ERROR_INVALID_PARAMETER;
1444
1445 if (!lstrcmpW(szUserSid, szLocalSid))
1446 return ERROR_INVALID_PARAMETER;
1447
1448 if (MSIREG_OpenUserDataProductKey(szProductCode, dwContext, NULL,
1449 &udprod, FALSE) != ERROR_SUCCESS)
1450 goto done;
1451
1452 if (MSIREG_OpenInstallProps(szProductCode, dwContext, NULL,
1453 &props, FALSE) != ERROR_SUCCESS)
1454 goto done;
1455
1456 r = ERROR_UNKNOWN_PATCH;
1457
1458 res = RegOpenKeyExW(udprod, szPatches, 0, KEY_READ, &patches);
1459 if (res != ERROR_SUCCESS)
1460 goto done;
1461
1462 res = RegOpenKeyExW(patches, squished_patch, 0, KEY_READ, &patch);
1463 if (res != ERROR_SUCCESS)
1464 goto done;
1465
1466 if (!lstrcmpW(szProperty, INSTALLPROPERTY_TRANSFORMSW))
1467 {
1468 if (MSIREG_OpenProductKey(szProductCode, NULL, dwContext,
1469 &prod, FALSE) != ERROR_SUCCESS)
1470 goto done;
1471
1472 res = RegOpenKeyExW(prod, szPatches, 0, KEY_ALL_ACCESS, &prodpatches);
1473 if (res != ERROR_SUCCESS)
1474 goto done;
1475
1476 datakey = prodpatches;
1477 szProperty = squished_patch;
1478 }
1479 else
1480 {
1481 if (MSIREG_OpenUserDataPatchKey(szPatchCode, dwContext,
1482 &udpatch, FALSE) != ERROR_SUCCESS)
1483 goto done;
1484
1485 if (!lstrcmpW(szProperty, INSTALLPROPERTY_LOCALPACKAGEW))
1486 {
1487 if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
1488 szProperty = szManagedPackage;
1489 datakey = udpatch;
1490 }
1491 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLDATEW))
1492 {
1493 datakey = patch;
1494 szProperty = szInstalled;
1495 }
1496 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_LOCALPACKAGEW))
1497 {
1498 datakey = udpatch;
1499 }
1500 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_UNINSTALLABLEW) ||
1501 !lstrcmpW(szProperty, INSTALLPROPERTY_PATCHSTATEW) ||
1502 !lstrcmpW(szProperty, INSTALLPROPERTY_DISPLAYNAMEW) ||
1503 !lstrcmpW(szProperty, INSTALLPROPERTY_MOREINFOURLW))
1504 {
1505 datakey = patch;
1506 }
1507 else
1508 {
1509 r = ERROR_UNKNOWN_PROPERTY;
1510 goto done;
1511 }
1512 }
1513
1514 val = msi_reg_get_val_str(datakey, szProperty);
1515 if (!val)
1516 val = strdupW(szEmpty);
1517
1518 r = ERROR_SUCCESS;
1519
1520 if (!pcchValue)
1521 goto done;
1522
1523 if (lpValue)
1524 lstrcpynW(lpValue, val, *pcchValue);
1525
1526 len = lstrlenW(val);
1527 if ((*val && *pcchValue < len + 1) || !lpValue)
1528 {
1529 if (lpValue)
1530 r = ERROR_MORE_DATA;
1531
1532 *pcchValue = len * sizeof(WCHAR);
1533 }
1534
1535 *pcchValue = len;
1536
1537 done:
1538 msi_free(val);
1539 RegCloseKey(prodpatches);
1540 RegCloseKey(prod);
1541 RegCloseKey(patch);
1542 RegCloseKey(patches);
1543 RegCloseKey(udpatch);
1544 RegCloseKey(props);
1545 RegCloseKey(udprod);
1546
1547 return r;
1548 }
1549
1550 UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes)
1551 {
1552 LPWSTR szwLogFile = NULL;
1553 UINT r;
1554
1555 TRACE("%08x %s %08x\n", dwLogMode, debugstr_a(szLogFile), attributes);
1556
1557 if( szLogFile )
1558 {
1559 szwLogFile = strdupAtoW( szLogFile );
1560 if( !szwLogFile )
1561 return ERROR_OUTOFMEMORY;
1562 }
1563 r = MsiEnableLogW( dwLogMode, szwLogFile, attributes );
1564 msi_free( szwLogFile );
1565 return r;
1566 }
1567
1568 UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, DWORD attributes)
1569 {
1570 HANDLE file = INVALID_HANDLE_VALUE;
1571
1572 TRACE("%08x %s %08x\n", dwLogMode, debugstr_w(szLogFile), attributes);
1573
1574 if (szLogFile)
1575 {
1576 lstrcpyW(gszLogFile,szLogFile);
1577 if (!(attributes & INSTALLLOGATTRIBUTES_APPEND))
1578 DeleteFileW(szLogFile);
1579 file = CreateFileW(szLogFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
1580 FILE_ATTRIBUTE_NORMAL, NULL);
1581 if (file != INVALID_HANDLE_VALUE)
1582 CloseHandle(file);
1583 else
1584 ERR("Unable to enable log %s\n",debugstr_w(szLogFile));
1585 }
1586 else
1587 gszLogFile[0] = '\0';
1588
1589 return ERROR_SUCCESS;
1590 }
1591
1592 UINT WINAPI MsiEnumComponentCostsW(MSIHANDLE hInstall, LPCWSTR szComponent,
1593 DWORD dwIndex, INSTALLSTATE iState,
1594 LPWSTR lpDriveBuf, DWORD *pcchDriveBuf,
1595 int *piCost, int *pTempCost)
1596 {
1597 FIXME("(%d, %s, %d, %d, %p, %p, %p %p): stub!\n", hInstall,
1598 debugstr_w(szComponent), dwIndex, iState, lpDriveBuf,
1599 pcchDriveBuf, piCost, pTempCost);
1600
1601 return ERROR_NO_MORE_ITEMS;
1602 }
1603
1604 UINT WINAPI MsiQueryComponentStateA(LPCSTR szProductCode,
1605 LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1606 LPCSTR szComponent, INSTALLSTATE *pdwState)
1607 {
1608 LPWSTR prodcode = NULL, usersid = NULL, comp = NULL;
1609 UINT r;
1610
1611 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_a(szProductCode),
1612 debugstr_a(szUserSid), dwContext, debugstr_a(szComponent), pdwState);
1613
1614 if (szProductCode && !(prodcode = strdupAtoW(szProductCode)))
1615 return ERROR_OUTOFMEMORY;
1616
1617 if (szUserSid && !(usersid = strdupAtoW(szUserSid)))
1618 return ERROR_OUTOFMEMORY;
1619
1620 if (szComponent && !(comp = strdupAtoW(szComponent)))
1621 return ERROR_OUTOFMEMORY;
1622
1623 r = MsiQueryComponentStateW(prodcode, usersid, dwContext, comp, pdwState);
1624
1625 msi_free(prodcode);
1626 msi_free(usersid);
1627 msi_free(comp);
1628
1629 return r;
1630 }
1631
1632 static BOOL msi_comp_find_prod_key(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
1633 {
1634 UINT r;
1635 HKEY hkey;
1636
1637 r = MSIREG_OpenProductKey(prodcode, NULL, context, &hkey, FALSE);
1638 RegCloseKey(hkey);
1639 return (r == ERROR_SUCCESS);
1640 }
1641
1642 static BOOL msi_comp_find_package(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
1643 {
1644 LPCWSTR package;
1645 HKEY hkey;
1646 DWORD sz;
1647 LONG res;
1648 UINT r;
1649
1650 static const WCHAR local_package[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0};
1651 static const WCHAR managed_local_package[] = {
1652 'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0
1653 };
1654
1655 r = MSIREG_OpenInstallProps(prodcode, context, NULL, &hkey, FALSE);
1656 if (r != ERROR_SUCCESS)
1657 return FALSE;
1658
1659 if (context == MSIINSTALLCONTEXT_USERMANAGED)
1660 package = managed_local_package;
1661 else
1662 package = local_package;
1663
1664 sz = 0;
1665 res = RegQueryValueExW(hkey, package, NULL, NULL, NULL, &sz);
1666 RegCloseKey(hkey);
1667
1668 return (res == ERROR_SUCCESS);
1669 }
1670
1671 static BOOL msi_comp_find_prodcode(LPWSTR squished_pc,
1672 MSIINSTALLCONTEXT context,
1673 LPCWSTR comp, LPWSTR val, DWORD *sz)
1674 {
1675 HKEY hkey;
1676 LONG res;
1677 UINT r;
1678
1679 if (context == MSIINSTALLCONTEXT_MACHINE)
1680 r = MSIREG_OpenUserDataComponentKey(comp, szLocalSid, &hkey, FALSE);
1681 else
1682 r = MSIREG_OpenUserDataComponentKey(comp, NULL, &hkey, FALSE);
1683
1684 if (r != ERROR_SUCCESS)
1685 return FALSE;
1686
1687 res = RegQueryValueExW(hkey, squished_pc, NULL, NULL, (BYTE *)val, sz);
1688 if (res != ERROR_SUCCESS)
1689 return FALSE;
1690
1691 RegCloseKey(hkey);
1692 return TRUE;
1693 }
1694
1695 UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode,
1696 LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1697 LPCWSTR szComponent, INSTALLSTATE *pdwState)
1698 {
1699 WCHAR squished_pc[GUID_SIZE];
1700 WCHAR val[MAX_PATH];
1701 BOOL found;
1702 DWORD sz;
1703
1704 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_w(szProductCode),
1705 debugstr_w(szUserSid), dwContext, debugstr_w(szComponent), pdwState);
1706
1707 if (!pdwState || !szComponent)
1708 return ERROR_INVALID_PARAMETER;
1709
1710 if (!szProductCode || !*szProductCode || lstrlenW(szProductCode) != GUID_SIZE - 1)
1711 return ERROR_INVALID_PARAMETER;
1712
1713 if (!squash_guid(szProductCode, squished_pc))
1714 return ERROR_INVALID_PARAMETER;
1715
1716 found = msi_comp_find_prod_key(szProductCode, dwContext);
1717
1718 if (!msi_comp_find_package(szProductCode, dwContext))
1719 {
1720 if (found)
1721 {
1722 *pdwState = INSTALLSTATE_UNKNOWN;
1723 return ERROR_UNKNOWN_COMPONENT;
1724 }
1725
1726 return ERROR_UNKNOWN_PRODUCT;
1727 }
1728
1729 *pdwState = INSTALLSTATE_UNKNOWN;
1730
1731 sz = MAX_PATH;
1732 if (!msi_comp_find_prodcode(squished_pc, dwContext, szComponent, val, &sz))
1733 return ERROR_UNKNOWN_COMPONENT;
1734
1735 if (sz == 0)
1736 *pdwState = INSTALLSTATE_NOTUSED;
1737 else
1738 {
1739 if (lstrlenW(val) > 2 &&
1740 val[0] >= '0' && val[0] <= '9' && val[1] >= '0' && val[1] <= '9')
1741 {
1742 *pdwState = INSTALLSTATE_SOURCE;
1743 }
1744 else
1745 *pdwState = INSTALLSTATE_LOCAL;
1746 }
1747
1748 return ERROR_SUCCESS;
1749 }
1750
1751 INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct)
1752 {
1753 LPWSTR szwProduct = NULL;
1754 INSTALLSTATE r;
1755
1756 if( szProduct )
1757 {
1758 szwProduct = strdupAtoW( szProduct );
1759 if( !szwProduct )
1760 return ERROR_OUTOFMEMORY;
1761 }
1762 r = MsiQueryProductStateW( szwProduct );
1763 msi_free( szwProduct );
1764 return r;
1765 }
1766
1767 INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct)
1768 {
1769 MSIINSTALLCONTEXT context = MSIINSTALLCONTEXT_USERUNMANAGED;
1770 INSTALLSTATE state = INSTALLSTATE_ADVERTISED;
1771 HKEY prodkey = 0, userdata = 0;
1772 DWORD val;
1773 UINT r;
1774
1775 static const WCHAR szWindowsInstaller[] = {
1776 'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
1777
1778 TRACE("%s\n", debugstr_w(szProduct));
1779
1780 if (!szProduct || !*szProduct)
1781 return INSTALLSTATE_INVALIDARG;
1782
1783 if (lstrlenW(szProduct) != GUID_SIZE - 1)
1784 return INSTALLSTATE_INVALIDARG;
1785
1786 if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
1787 &prodkey, FALSE) != ERROR_SUCCESS &&
1788 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1789 &prodkey, FALSE) != ERROR_SUCCESS &&
1790 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
1791 &prodkey, FALSE) == ERROR_SUCCESS)
1792 {
1793 context = MSIINSTALLCONTEXT_MACHINE;
1794 }
1795
1796 r = MSIREG_OpenInstallProps(szProduct, context, NULL, &userdata, FALSE);
1797 if (r != ERROR_SUCCESS)
1798 goto done;
1799
1800 if (!msi_reg_get_val_dword(userdata, szWindowsInstaller, &val))
1801 goto done;
1802
1803 if (val)
1804 state = INSTALLSTATE_DEFAULT;
1805 else
1806 state = INSTALLSTATE_UNKNOWN;
1807
1808 done:
1809 if (!prodkey)
1810 {
1811 state = INSTALLSTATE_UNKNOWN;
1812
1813 if (userdata)
1814 state = INSTALLSTATE_ABSENT;
1815 }
1816
1817 RegCloseKey(prodkey);
1818 RegCloseKey(userdata);
1819 return state;
1820 }
1821
1822 INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd)
1823 {
1824 INSTALLUILEVEL old = gUILevel;
1825 HWND oldwnd = gUIhwnd;
1826
1827 TRACE("%08x %p\n", dwUILevel, phWnd);
1828
1829 gUILevel = dwUILevel;
1830 if (phWnd)
1831 {
1832 gUIhwnd = *phWnd;
1833 *phWnd = oldwnd;
1834 }
1835 return old;
1836 }
1837
1838 INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler,
1839 DWORD dwMessageFilter, LPVOID pvContext)
1840 {
1841 INSTALLUI_HANDLERA prev = gUIHandlerA;
1842
1843 TRACE("%p %x %p\n",puiHandler, dwMessageFilter,pvContext);
1844 gUIHandlerA = puiHandler;
1845 gUIFilter = dwMessageFilter;
1846 gUIContext = pvContext;
1847
1848 return prev;
1849 }
1850
1851 INSTALLUI_HANDLERW WINAPI MsiSetExternalUIW(INSTALLUI_HANDLERW puiHandler,
1852 DWORD dwMessageFilter, LPVOID pvContext)
1853 {
1854 INSTALLUI_HANDLERW prev = gUIHandlerW;
1855
1856 TRACE("%p %x %p\n",puiHandler,dwMessageFilter,pvContext);
1857 gUIHandlerW = puiHandler;
1858 gUIFilter = dwMessageFilter;
1859 gUIContext = pvContext;
1860
1861 return prev;
1862 }
1863
1864 /******************************************************************
1865 * MsiLoadStringW [MSI.@]
1866 *
1867 * Loads a string from MSI's string resources.
1868 *
1869 * PARAMS
1870 *
1871 * handle [I] only -1 is handled currently
1872 * id [I] id of the string to be loaded
1873 * lpBuffer [O] buffer for the string to be written to
1874 * nBufferMax [I] maximum size of the buffer in characters
1875 * lang [I] the preferred language for the string
1876 *
1877 * RETURNS
1878 *
1879 * If successful, this function returns the language id of the string loaded
1880 * If the function fails, the function returns zero.
1881 *
1882 * NOTES
1883 *
1884 * The type of the first parameter is unknown. LoadString's prototype
1885 * suggests that it might be a module handle. I have made it an MSI handle
1886 * for starters, as -1 is an invalid MSI handle, but not an invalid module
1887 * handle. Maybe strings can be stored in an MSI database somehow.
1888 */
1889 LANGID WINAPI MsiLoadStringW( MSIHANDLE handle, UINT id, LPWSTR lpBuffer,
1890 int nBufferMax, LANGID lang )
1891 {
1892 HRSRC hres;
1893 HGLOBAL hResData;
1894 LPWSTR p;
1895 DWORD i, len;
1896
1897 TRACE("%d %u %p %d %d\n", handle, id, lpBuffer, nBufferMax, lang);
1898
1899 if( handle != -1 )
1900 FIXME("don't know how to deal with handle = %08x\n", handle);
1901
1902 if( !lang )
1903 lang = GetUserDefaultLangID();
1904
1905 hres = FindResourceExW( msi_hInstance, (LPCWSTR) RT_STRING,
1906 (LPWSTR)1, lang );
1907 if( !hres )
1908 return 0;
1909 hResData = LoadResource( msi_hInstance, hres );
1910 if( !hResData )
1911 return 0;
1912 p = LockResource( hResData );
1913 if( !p )
1914 return 0;
1915
1916 for (i = 0; i < (id&0xf); i++)
1917 p += *p + 1;
1918 len = *p;
1919
1920 if( nBufferMax <= len )
1921 return 0;
1922
1923 memcpy( lpBuffer, p+1, len * sizeof(WCHAR));
1924 lpBuffer[ len ] = 0;
1925
1926 TRACE("found -> %s\n", debugstr_w(lpBuffer));
1927
1928 return lang;
1929 }
1930
1931 LANGID WINAPI MsiLoadStringA( MSIHANDLE handle, UINT id, LPSTR lpBuffer,
1932 int nBufferMax, LANGID lang )
1933 {
1934 LPWSTR bufW;
1935 LANGID r;
1936 INT len;
1937
1938 bufW = msi_alloc(nBufferMax*sizeof(WCHAR));
1939 r = MsiLoadStringW(handle, id, bufW, nBufferMax, lang);
1940 if( r )
1941 {
1942 len = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL );
1943 if( len <= nBufferMax )
1944 WideCharToMultiByte( CP_ACP, 0, bufW, -1,
1945 lpBuffer, nBufferMax, NULL, NULL );
1946 else
1947 r = 0;
1948 }
1949 msi_free(bufW);
1950 return r;
1951 }
1952
1953 INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf,
1954 LPDWORD pcchBuf)
1955 {
1956 char szProduct[GUID_SIZE];
1957
1958 TRACE("%s %p %p\n", debugstr_a(szComponent), lpPathBuf, pcchBuf);
1959
1960 if (MsiGetProductCodeA( szComponent, szProduct ) != ERROR_SUCCESS)
1961 return INSTALLSTATE_UNKNOWN;
1962
1963 return MsiGetComponentPathA( szProduct, szComponent, lpPathBuf, pcchBuf );
1964 }
1965
1966 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPWSTR lpPathBuf,
1967 LPDWORD pcchBuf)
1968 {
1969 WCHAR szProduct[GUID_SIZE];
1970
1971 TRACE("%s %p %p\n", debugstr_w(szComponent), lpPathBuf, pcchBuf);
1972
1973 if (MsiGetProductCodeW( szComponent, szProduct ) != ERROR_SUCCESS)
1974 return INSTALLSTATE_UNKNOWN;
1975
1976 return MsiGetComponentPathW( szProduct, szComponent, lpPathBuf, pcchBuf );
1977 }
1978
1979 UINT WINAPI MsiMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType,
1980 WORD wLanguageId, DWORD f)
1981 {
1982 FIXME("%p %s %s %u %08x %08x\n", hWnd, debugstr_a(lpText), debugstr_a(lpCaption),
1983 uType, wLanguageId, f);
1984 return MessageBoxExA(hWnd,lpText,lpCaption,uType,wLanguageId);
1985 }
1986
1987 UINT WINAPI MsiMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType,
1988 WORD wLanguageId, DWORD f)
1989 {
1990 FIXME("%p %s %s %u %08x %08x\n", hWnd, debugstr_w(lpText), debugstr_w(lpCaption),
1991 uType, wLanguageId, f);
1992 return MessageBoxExW(hWnd,lpText,lpCaption,uType,wLanguageId);
1993 }
1994
1995 UINT WINAPI MsiProvideAssemblyA( LPCSTR szAssemblyName, LPCSTR szAppContext,
1996 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf,
1997 LPDWORD pcchPathBuf )
1998 {
1999 FIXME("%s %s %08x %08x %p %p\n", debugstr_a(szAssemblyName),
2000 debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
2001 pcchPathBuf);
2002 return ERROR_CALL_NOT_IMPLEMENTED;
2003 }
2004
2005 UINT WINAPI MsiProvideAssemblyW( LPCWSTR szAssemblyName, LPCWSTR szAppContext,
2006 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf,
2007 LPDWORD pcchPathBuf )
2008 {
2009 FIXME("%s %s %08x %08x %p %p\n", debugstr_w(szAssemblyName),
2010 debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
2011 pcchPathBuf);
2012 return ERROR_CALL_NOT_IMPLEMENTED;
2013 }
2014
2015 UINT WINAPI MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor,
2016 LPSTR szPath, LPDWORD pcchPath, LPDWORD pcchArgs )
2017 {
2018 FIXME("%s %p %p %p\n", debugstr_a(szDescriptor), szPath, pcchPath, pcchArgs );
2019 return ERROR_CALL_NOT_IMPLEMENTED;
2020 }
2021
2022 UINT WINAPI MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor,
2023 LPWSTR szPath, LPDWORD pcchPath, LPDWORD pcchArgs )
2024 {
2025 FIXME("%s %p %p %p\n", debugstr_w(szDescriptor), szPath, pcchPath, pcchArgs );
2026 return ERROR_CALL_NOT_IMPLEMENTED;
2027 }
2028
2029 HRESULT WINAPI MsiGetFileSignatureInformationA( LPCSTR szSignedObjectPath,
2030 DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, LPBYTE pbHashData,
2031 LPDWORD pcbHashData)
2032 {
2033 FIXME("%s %08x %p %p %p\n", debugstr_a(szSignedObjectPath), dwFlags,
2034 ppcCertContext, pbHashData, pcbHashData);
2035 return ERROR_CALL_NOT_IMPLEMENTED;
2036 }
2037
2038 HRESULT WINAPI MsiGetFileSignatureInformationW( LPCWSTR szSignedObjectPath,
2039 DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, LPBYTE pbHashData,
2040 LPDWORD pcbHashData)
2041 {
2042 FIXME("%s %08x %p %p %p\n", debugstr_w(szSignedObjectPath), dwFlags,
2043 ppcCertContext, pbHashData, pcbHashData);
2044 return ERROR_CALL_NOT_IMPLEMENTED;
2045 }
2046
2047 /******************************************************************
2048 * MsiGetProductPropertyA [MSI.@]
2049 */
2050 UINT WINAPI MsiGetProductPropertyA(MSIHANDLE hProduct, LPCSTR szProperty,
2051 LPSTR szValue, LPDWORD pccbValue)
2052 {
2053 LPWSTR prop = NULL, val = NULL;
2054 DWORD len;
2055 UINT r;
2056
2057 TRACE("(%d, %s, %p, %p)\n", hProduct, debugstr_a(szProperty),
2058 szValue, pccbValue);
2059
2060 if (szValue && !pccbValue)
2061 return ERROR_INVALID_PARAMETER;
2062
2063 if (szProperty) prop = strdupAtoW(szProperty);
2064
2065 len = 0;
2066 r = MsiGetProductPropertyW(hProduct, prop, NULL, &len);
2067 if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
2068 goto done;
2069
2070 if (r == ERROR_SUCCESS)
2071 {
2072 if (szValue) *szValue = '\0';
2073 if (pccbValue) *pccbValue = 0;
2074 goto done;
2075 }
2076
2077 val = msi_alloc(++len * sizeof(WCHAR));
2078 if (!val)
2079 {
2080 r = ERROR_OUTOFMEMORY;
2081 goto done;
2082 }
2083
2084 r = MsiGetProductPropertyW(hProduct, prop, val, &len);
2085 if (r != ERROR_SUCCESS)
2086 goto done;
2087
2088 len = WideCharToMultiByte(CP_ACP, 0, val, -1, NULL, 0, NULL, NULL);
2089
2090 if (szValue)
2091 WideCharToMultiByte(CP_ACP, 0, val, -1, szValue,
2092 *pccbValue, NULL, NULL);
2093
2094 if (pccbValue)
2095 {
2096 if (len > *pccbValue)
2097 r = ERROR_MORE_DATA;
2098
2099 *pccbValue = len - 1;
2100 }
2101
2102 done:
2103 msi_free(prop);
2104 msi_free(val);
2105
2106 return r;
2107 }
2108
2109 /******************************************************************
2110 * MsiGetProductPropertyW [MSI.@]
2111 */
2112 UINT WINAPI MsiGetProductPropertyW(MSIHANDLE hProduct, LPCWSTR szProperty,
2113 LPWSTR szValue, LPDWORD pccbValue)
2114 {
2115 MSIPACKAGE *package;
2116 MSIQUERY *view = NULL;
2117 MSIRECORD *rec = NULL;
2118 LPCWSTR val;
2119 UINT r;
2120
2121 static const WCHAR query[] = {
2122 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
2123 '`','P','r','o','p','e','r','t','y','`',' ','W','H','E','R','E',' ',
2124 '`','P','r','o','p','e','r','t','y','`','=','\'','%','s','\'',0};
2125
2126 TRACE("(%d, %s, %p, %p)\n", hProduct, debugstr_w(szProperty),
2127 szValue, pccbValue);
2128
2129 if (!szProperty)
2130 return ERROR_INVALID_PARAMETER;
2131
2132 if (szValue && !pccbValue)
2133 return ERROR_INVALID_PARAMETER;
2134
2135 package = msihandle2msiinfo(hProduct, MSIHANDLETYPE_PACKAGE);
2136 if (!package)
2137 return ERROR_INVALID_HANDLE;
2138
2139 r = MSI_OpenQuery(package->db, &view, query, szProperty);
2140 if (r != ERROR_SUCCESS)
2141 goto done;
2142
2143 r = MSI_ViewExecute(view, 0);
2144 if (r != ERROR_SUCCESS)
2145 goto done;
2146
2147 r = MSI_ViewFetch(view, &rec);
2148 if (r != ERROR_SUCCESS)
2149 goto done;
2150
2151 val = MSI_RecordGetString(rec, 2);
2152 if (!val)
2153 goto done;
2154
2155 if (lstrlenW(val) >= *pccbValue)
2156 {
2157 lstrcpynW(szValue, val, *pccbValue);
2158 *pccbValue = lstrlenW(val);
2159 r = ERROR_MORE_DATA;
2160 }
2161 else
2162 {
2163 lstrcpyW(szValue, val);
2164 *pccbValue = lstrlenW(val);
2165 r = ERROR_SUCCESS;
2166 }
2167
2168 done:
2169 if (view)
2170 {
2171 MSI_ViewClose(view);
2172 msiobj_release(&view->hdr);
2173 if (rec) msiobj_release(&rec->hdr);
2174 }
2175
2176 if (!rec)
2177 {
2178 if (szValue) *szValue = '\0';
2179 if (pccbValue) *pccbValue = 0;
2180 r = ERROR_SUCCESS;
2181 }
2182
2183 return r;
2184 }
2185
2186 UINT WINAPI MsiVerifyPackageA( LPCSTR szPackage )
2187 {
2188 UINT r;
2189 LPWSTR szPack = NULL;
2190
2191 TRACE("%s\n", debugstr_a(szPackage) );
2192
2193 if( szPackage )
2194 {
2195 szPack = strdupAtoW( szPackage );
2196 if( !szPack )
2197 return ERROR_OUTOFMEMORY;
2198 }
2199
2200 r = MsiVerifyPackageW( szPack );
2201
2202 msi_free( szPack );
2203
2204 return r;
2205 }
2206
2207 UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage )
2208 {
2209 MSIHANDLE handle;
2210 UINT r;
2211
2212 TRACE("%s\n", debugstr_w(szPackage) );
2213
2214 r = MsiOpenDatabaseW( szPackage, MSIDBOPEN_READONLY, &handle );
2215 MsiCloseHandle( handle );
2216
2217 return r;
2218 }
2219
2220 static INSTALLSTATE MSI_GetComponentPath(LPCWSTR szProduct, LPCWSTR szComponent,
2221 awstring* lpPathBuf, LPDWORD pcchBuf)
2222 {
2223 WCHAR squished_pc[GUID_SIZE];
2224 WCHAR squished_comp[GUID_SIZE];
2225 HKEY hkey;
2226 LPWSTR path = NULL;
2227 INSTALLSTATE state;
2228 DWORD version;
2229
2230 static const WCHAR wininstaller[] = {
2231 'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
2232
2233 TRACE("%s %s %p %p\n", debugstr_w(szProduct),
2234 debugstr_w(szComponent), lpPathBuf->str.w, pcchBuf);
2235
2236 if (!szProduct || !szComponent)
2237 return INSTALLSTATE_INVALIDARG;
2238
2239 if (lpPathBuf->str.w && !pcchBuf)
2240 return INSTALLSTATE_INVALIDARG;
2241
2242 if (!squash_guid(szProduct, squished_pc) ||
2243 !squash_guid(szComponent, squished_comp))
2244 return INSTALLSTATE_INVALIDARG;
2245
2246 state = INSTALLSTATE_UNKNOWN;
2247
2248 if (MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &hkey, FALSE) == ERROR_SUCCESS ||
2249 MSIREG_OpenUserDataComponentKey(szComponent, NULL, &hkey, FALSE) == ERROR_SUCCESS)
2250 {
2251 path = msi_reg_get_val_str(hkey, squished_pc);
2252 RegCloseKey(hkey);
2253
2254 state = INSTALLSTATE_ABSENT;
2255
2256 if ((MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE, NULL,
2257 &hkey, FALSE) == ERROR_SUCCESS ||
2258 MSIREG_OpenUserDataProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
2259 NULL, &hkey, FALSE) == ERROR_SUCCESS) &&
2260 msi_reg_get_val_dword(hkey, wininstaller, &version) &&
2261 GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES)
2262 {
2263 RegCloseKey(hkey);
2264 state = INSTALLSTATE_LOCAL;
2265 }
2266 }
2267
2268 if (state != INSTALLSTATE_LOCAL &&
2269 (MSIREG_OpenProductKey(szProduct, NULL,
2270 MSIINSTALLCONTEXT_USERUNMANAGED,
2271 &hkey, FALSE) == ERROR_SUCCESS ||
2272 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
2273 &hkey, FALSE) == ERROR_SUCCESS))
2274 {
2275 RegCloseKey(hkey);
2276
2277 if (MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &hkey, FALSE) == ERROR_SUCCESS ||
2278 MSIREG_OpenUserDataComponentKey(szComponent, NULL, &hkey, FALSE) == ERROR_SUCCESS)
2279 {
2280 msi_free(path);
2281 path = msi_reg_get_val_str(hkey, squished_pc);
2282 RegCloseKey(hkey);
2283
2284 state = INSTALLSTATE_ABSENT;
2285
2286 if (GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES)
2287 state = INSTALLSTATE_LOCAL;
2288 }
2289 }
2290
2291 if (!path)
2292 return INSTALLSTATE_UNKNOWN;
2293
2294 if (state == INSTALLSTATE_LOCAL && !*path)
2295 state = INSTALLSTATE_NOTUSED;
2296
2297 msi_strcpy_to_awstring(path, lpPathBuf, pcchBuf);
2298 msi_free(path);
2299 return state;
2300 }
2301
2302 /******************************************************************
2303 * MsiGetComponentPathW [MSI.@]
2304 */
2305 INSTALLSTATE WINAPI MsiGetComponentPathW(LPCWSTR szProduct, LPCWSTR szComponent,
2306 LPWSTR lpPathBuf, LPDWORD pcchBuf)
2307 {
2308 awstring path;
2309
2310 path.unicode = TRUE;
2311 path.str.w = lpPathBuf;
2312
2313 return MSI_GetComponentPath( szProduct, szComponent, &path, pcchBuf );
2314 }
2315
2316 /******************************************************************
2317 * MsiGetComponentPathA [MSI.@]
2318 */
2319 INSTALLSTATE WINAPI MsiGetComponentPathA(LPCSTR szProduct, LPCSTR szComponent,
2320 LPSTR lpPathBuf, LPDWORD pcchBuf)
2321 {
2322 LPWSTR szwProduct, szwComponent = NULL;
2323 INSTALLSTATE r = INSTALLSTATE_UNKNOWN;
2324 awstring path;
2325
2326 szwProduct = strdupAtoW( szProduct );
2327 if( szProduct && !szwProduct)
2328 goto end;
2329
2330 szwComponent = strdupAtoW( szComponent );
2331 if( szComponent && !szwComponent )
2332 goto end;
2333
2334 path.unicode = FALSE;
2335 path.str.a = lpPathBuf;
2336
2337 r = MSI_GetComponentPath( szwProduct, szwComponent, &path, pcchBuf );
2338
2339 end:
2340 msi_free( szwProduct );
2341 msi_free( szwComponent );
2342
2343 return r;
2344 }
2345
2346 /******************************************************************
2347 * MsiQueryFeatureStateA [MSI.@]
2348 */
2349 INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature)
2350 {
2351 LPWSTR szwProduct = NULL, szwFeature= NULL;
2352 INSTALLSTATE rc = INSTALLSTATE_UNKNOWN;
2353
2354 szwProduct = strdupAtoW( szProduct );
2355 if ( szProduct && !szwProduct )
2356 goto end;
2357
2358 szwFeature = strdupAtoW( szFeature );
2359 if ( szFeature && !szwFeature )
2360 goto end;
2361
2362 rc = MsiQueryFeatureStateW(szwProduct, szwFeature);
2363
2364 end:
2365 msi_free( szwProduct);
2366 msi_free( szwFeature);
2367
2368 return rc;
2369 }
2370
2371 /******************************************************************
2372 * MsiQueryFeatureStateW [MSI.@]
2373 *
2374 * Checks the state of a feature
2375 *
2376 * PARAMS
2377 * szProduct [I] Product's GUID string
2378 * szFeature [I] Feature's GUID string
2379 *
2380 * RETURNS
2381 * INSTALLSTATE_LOCAL Feature is installed and usable
2382 * INSTALLSTATE_ABSENT Feature is absent
2383 * INSTALLSTATE_ADVERTISED Feature should be installed on demand
2384 * INSTALLSTATE_UNKNOWN An error occurred
2385 * INSTALLSTATE_INVALIDARG One of the GUIDs was invalid
2386 *
2387 */
2388 INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature)
2389 {
2390 WCHAR squishProduct[33], comp[GUID_SIZE];
2391 GUID guid;
2392 LPWSTR components, p, parent_feature, path;
2393 UINT rc;
2394 HKEY hkey;
2395 INSTALLSTATE r;
2396 BOOL missing = FALSE;
2397 BOOL machine = FALSE;
2398 BOOL source = FALSE;
2399
2400 TRACE("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature));
2401
2402 if (!szProduct || !szFeature)
2403 return INSTALLSTATE_INVALIDARG;
2404
2405 if (!squash_guid( szProduct, squishProduct ))
2406 return INSTALLSTATE_INVALIDARG;
2407
2408 if (MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
2409 &hkey, FALSE) != ERROR_SUCCESS &&
2410 MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
2411 &hkey, FALSE) != ERROR_SUCCESS)
2412 {
2413 rc = MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
2414 &hkey, FALSE);
2415 if (rc != ERROR_SUCCESS)
2416 return INSTALLSTATE_UNKNOWN;
2417
2418 machine = TRUE;
2419 }
2420
2421 parent_feature = msi_reg_get_val_str( hkey, szFeature );
2422 RegCloseKey(hkey);
2423
2424 if (!parent_feature)
2425 return INSTALLSTATE_UNKNOWN;
2426
2427 r = (parent_feature[0] == 6) ? INSTALLSTATE_ABSENT : INSTALLSTATE_LOCAL;
2428 msi_free(parent_feature);
2429 if (r == INSTALLSTATE_ABSENT)
2430 return r;
2431
2432 if (machine)
2433 rc = MSIREG_OpenUserDataFeaturesKey(szProduct,
2434 MSIINSTALLCONTEXT_MACHINE,
2435 &hkey, FALSE);
2436 else
2437 rc = MSIREG_OpenUserDataFeaturesKey(szProduct,
2438 MSIINSTALLCONTEXT_USERUNMANAGED,
2439 &hkey, FALSE);
2440
2441 if (rc != ERROR_SUCCESS)
2442 return INSTALLSTATE_ADVERTISED;
2443
2444 components = msi_reg_get_val_str( hkey, szFeature );
2445 RegCloseKey(hkey);
2446
2447 TRACE("rc = %d buffer = %s\n", rc, debugstr_w(components));
2448
2449 if (!components)
2450 return INSTALLSTATE_ADVERTISED;
2451
2452 for( p = components; *p && *p != 2 ; p += 20)
2453 {
2454 if (!decode_base85_guid( p, &guid ))
2455 {
2456 if (p != components)
2457 break;
2458
2459 msi_free(components);
2460 return INSTALLSTATE_BADCONFIG;
2461 }
2462
2463 StringFromGUID2(&guid, comp, GUID_SIZE);
2464
2465 if (machine)
2466 rc = MSIREG_OpenUserDataComponentKey(comp, szLocalSid, &hkey, FALSE);
2467 else
2468 rc = MSIREG_OpenUserDataComponentKey(comp, NULL, &hkey, FALSE);
2469
2470 if (rc != ERROR_SUCCESS)
2471 {
2472 msi_free(components);
2473 return INSTALLSTATE_ADVERTISED;
2474 }
2475
2476 path = msi_reg_get_val_str(hkey, squishProduct);
2477 if (!path)
2478 missing = TRUE;
2479 else if (lstrlenW(path) > 2 &&
2480 path[0] >= '0' && path[0] <= '9' &&
2481 path[1] >= '0' && path[1] <= '9')
2482 {
2483 source = TRUE;
2484 }
2485
2486 msi_free(path);
2487 }
2488
2489 TRACE("%s %s -> %d\n", debugstr_w(szProduct), debugstr_w(szFeature), r);
2490 msi_free(components);
2491
2492 if (missing)
2493 return INSTALLSTATE_ADVERTISED;
2494
2495 if (source)
2496 return INSTALLSTATE_SOURCE;
2497
2498 return INSTALLSTATE_LOCAL;
2499 }
2500
2501 /******************************************************************
2502 * MsiGetFileVersionA [MSI.@]
2503 */
2504 UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf,
2505 LPDWORD pcchVersionBuf, LPSTR lpLangBuf, LPDWORD pcchLangBuf)
2506 {
2507 LPWSTR szwFilePath = NULL, lpwVersionBuff = NULL, lpwLangBuff = NULL;
2508 UINT ret = ERROR_OUTOFMEMORY;
2509
2510 if ((lpVersionBuf && !pcchVersionBuf) ||
2511 (lpLangBuf && !pcchLangBuf))
2512 return ERROR_INVALID_PARAMETER;
2513
2514 if( szFilePath )
2515 {
2516 szwFilePath = strdupAtoW( szFilePath );
2517 if( !szwFilePath )
2518 goto end;
2519 }
2520
2521 if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf )
2522 {
2523 lpwVersionBuff = msi_alloc(*pcchVersionBuf*sizeof(WCHAR));
2524 if( !lpwVersionBuff )
2525 goto end;
2526 }
2527
2528 if( lpLangBuf && pcchLangBuf && *pcchLangBuf )
2529 {
2530 lpwLangBuff = msi_alloc(*pcchLangBuf*sizeof(WCHAR));
2531 if( !lpwLangBuff )
2532 goto end;
2533 }
2534
2535 ret = MsiGetFileVersionW(szwFilePath, lpwVersionBuff, pcchVersionBuf,
2536 lpwLangBuff, pcchLangBuf);
2537
2538 if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwVersionBuff )
2539 WideCharToMultiByte(CP_ACP, 0, lpwVersionBuff, -1,
2540 lpVersionBuf, *pcchVersionBuf + 1, NULL, NULL);
2541 if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwLangBuff )
2542 WideCharToMultiByte(CP_ACP, 0, lpwLangBuff, -1,
2543 lpLangBuf, *pcchLangBuf + 1, NULL, NULL);
2544
2545 end:
2546 msi_free(szwFilePath);
2547 msi_free(lpwVersionBuff);
2548 msi_free(lpwLangBuff);
2549
2550 return ret;
2551 }
2552
2553 /******************************************************************
2554 * MsiGetFileVersionW [MSI.@]
2555 */
2556 UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf,
2557 LPDWORD pcchVersionBuf, LPWSTR lpLangBuf, LPDWORD pcchLangBuf)
2558 {
2559 static const WCHAR szVersionResource[] = {'\\',0};
2560 static const WCHAR szVersionFormat[] = {
2561 '%','d','.','%','d','.','%','d','.','%','d',0};
2562 static const WCHAR szLangResource[] = {
2563 '\\','V','a','r','F','i','l','e','I','n','f','o','\\',
2564 'T','r','a','n','s','l','a','t','i','o','n',0};
2565 static const WCHAR szLangFormat[] = {'%','d',0};
2566 UINT ret = 0;
2567 DWORD dwVerLen, gle;
2568 LPVOID lpVer = NULL;
2569 VS_FIXEDFILEINFO *ffi;
2570 USHORT *lang;
2571 UINT puLen;
2572 WCHAR tmp[32];
2573
2574 TRACE("%s %p %d %p %d\n", debugstr_w(szFilePath),
2575 lpVersionBuf, pcchVersionBuf?*pcchVersionBuf:0,
2576 lpLangBuf, pcchLangBuf?*pcchLangBuf:0);
2577
2578 if ((lpVersionBuf && !pcchVersionBuf) ||
2579 (lpLangBuf && !pcchLangBuf))
2580 return ERROR_INVALID_PARAMETER;
2581
2582 dwVerLen = GetFileVersionInfoSizeW(szFilePath, NULL);
2583 if( !dwVerLen )
2584 {
2585 gle = GetLastError();
2586 if (gle == ERROR_BAD_PATHNAME)
2587 return ERROR_FILE_NOT_FOUND;
2588 else if (gle == ERROR_RESOURCE_DATA_NOT_FOUND)
2589 return ERROR_FILE_INVALID;
2590
2591 return gle;
2592 }
2593
2594 lpVer = msi_alloc(dwVerLen);
2595 if( !lpVer )
2596 {
2597 ret = ERROR_OUTOFMEMORY;
2598 goto end;
2599 }
2600
2601 if( !GetFileVersionInfoW(szFilePath, 0, dwVerLen, lpVer) )
2602 {
2603 ret = GetLastError();
2604 goto end;
2605 }
2606
2607 if (pcchVersionBuf)
2608 {
2609 if( VerQueryValueW(lpVer, szVersionResource, (LPVOID*)&ffi, &puLen) &&
2610 (puLen > 0) )
2611 {
2612 wsprintfW(tmp, szVersionFormat,
2613 HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS),
2614 HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS));
2615 if (lpVersionBuf) lstrcpynW(lpVersionBuf, tmp, *pcchVersionBuf);
2616
2617 if (strlenW(tmp) >= *pcchVersionBuf)
2618 ret = ERROR_MORE_DATA;
2619
2620 *pcchVersionBuf = lstrlenW(tmp);
2621 }
2622 else
2623 {
2624 if (lpVersionBuf) *lpVersionBuf = 0;
2625 *pcchVersionBuf = 0;
2626 }
2627 }
2628
2629 if (pcchLangBuf)
2630 {
2631 if (VerQueryValueW(lpVer, szLangResource, (LPVOID*)&lang, &puLen) &&
2632 (puLen > 0))
2633 {
2634 wsprintfW(tmp, szLangFormat, *lang);
2635 if (lpLangBuf) lstrcpynW(lpLangBuf, tmp, *pcchLangBuf);
2636
2637 if (strlenW(tmp) >= *pcchLangBuf)
2638 ret = ERROR_MORE_DATA;
2639
2640 *pcchLangBuf = lstrlenW(tmp);
2641 }
2642 else
2643 {
2644 if (lpLangBuf) *lpLangBuf = 0;
2645 *pcchLangBuf = 0;
2646 }
2647 }
2648
2649 end:
2650 msi_free(lpVer);
2651 return ret;
2652 }
2653
2654 /***********************************************************************
2655 * MsiGetFeatureUsageW [MSI.@]
2656 */
2657 UINT WINAPI MsiGetFeatureUsageW( LPCWSTR szProduct, LPCWSTR szFeature,
2658 LPDWORD pdwUseCount, LPWORD pwDateUsed )
2659 {
2660 FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szFeature),
2661 pdwUseCount, pwDateUsed);
2662 return ERROR_CALL_NOT_IMPLEMENTED;
2663 }
2664
2665 /***********************************************************************
2666 * MsiGetFeatureUsageA [MSI.@]
2667 */
2668 UINT WINAPI MsiGetFeatureUsageA( LPCSTR szProduct, LPCSTR szFeature,
2669 LPDWORD pdwUseCount, LPWORD pwDateUsed )
2670 {
2671 LPWSTR prod = NULL, feat = NULL;
2672 UINT ret = ERROR_OUTOFMEMORY;
2673
2674 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szFeature),
2675 pdwUseCount, pwDateUsed);
2676
2677 prod = strdupAtoW( szProduct );
2678 if (szProduct && !prod)
2679 goto end;
2680
2681 feat = strdupAtoW( szFeature );
2682 if (szFeature && !feat)
2683 goto end;
2684
2685 ret = MsiGetFeatureUsageW( prod, feat, pdwUseCount, pwDateUsed );
2686
2687 end:
2688 msi_free( prod );
2689 msi_free( feat );
2690
2691 return ret;
2692 }
2693
2694 /***********************************************************************
2695 * MsiUseFeatureExW [MSI.@]
2696 */
2697 INSTALLSTATE WINAPI MsiUseFeatureExW( LPCWSTR szProduct, LPCWSTR szFeature,
2698 DWORD dwInstallMode, DWORD dwReserved )
2699 {
2700 INSTALLSTATE state;
2701
2702 TRACE("%s %s %i %i\n", debugstr_w(szProduct), debugstr_w(szFeature),
2703 dwInstallMode, dwReserved);
2704
2705 state = MsiQueryFeatureStateW( szProduct, szFeature );
2706
2707 if (dwReserved)
2708 return INSTALLSTATE_INVALIDARG;
2709
2710 if (state == INSTALLSTATE_LOCAL && dwInstallMode != INSTALLMODE_NODETECTION)
2711 {
2712 FIXME("mark product %s feature %s as used\n",
2713 debugstr_w(szProduct), debugstr_w(szFeature) );
2714 }
2715
2716 return state;
2717 }
2718
2719 /***********************************************************************
2720 * MsiUseFeatureExA [MSI.@]
2721 */
2722 INSTALLSTATE WINAPI MsiUseFeatureExA( LPCSTR szProduct, LPCSTR szFeature,
2723 DWORD dwInstallMode, DWORD dwReserved )
2724 {
2725 INSTALLSTATE ret = INSTALLSTATE_UNKNOWN;
2726 LPWSTR prod = NULL, feat = NULL;
2727
2728 TRACE("%s %s %i %i\n", debugstr_a(szProduct), debugstr_a(szFeature),
2729 dwInstallMode, dwReserved);
2730
2731 prod = strdupAtoW( szProduct );
2732 if (szProduct && !prod)
2733 goto end;
2734
2735 feat = strdupAtoW( szFeature );
2736 if (szFeature && !feat)
2737 goto end;
2738
2739 ret = MsiUseFeatureExW( prod, feat, dwInstallMode, dwReserved );
2740
2741 end:
2742 msi_free( prod );
2743 msi_free( feat );
2744
2745 return ret;
2746 }
2747
2748 /***********************************************************************
2749 * MsiUseFeatureW [MSI.@]
2750 */
2751 INSTALLSTATE WINAPI MsiUseFeatureW( LPCWSTR szProduct, LPCWSTR szFeature )
2752 {
2753 return MsiUseFeatureExW(szProduct, szFeature, 0, 0);
2754 }
2755
2756 /***********************************************************************
2757 * MsiUseFeatureA [MSI.@]
2758 */
2759 INSTALLSTATE WINAPI MsiUseFeatureA( LPCSTR szProduct, LPCSTR szFeature )
2760 {
2761 return MsiUseFeatureExA(szProduct, szFeature, 0, 0);
2762 }
2763
2764 /***********************************************************************
2765 * MSI_ProvideQualifiedComponentEx [internal]
2766 */
2767 static UINT MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent,
2768 LPCWSTR szQualifier, DWORD dwInstallMode, LPCWSTR szProduct,
2769 DWORD Unused1, DWORD Unused2, awstring *lpPathBuf,
2770 LPDWORD pcchPathBuf)
2771 {
2772 WCHAR product[MAX_FEATURE_CHARS+1], component[MAX_FEATURE_CHARS+1],
2773 feature[MAX_FEATURE_CHARS+1];
2774 LPWSTR info;
2775 HKEY hkey;
2776 DWORD sz;
2777 UINT rc;
2778
2779 TRACE("%s %s %i %s %i %i %p %p\n", debugstr_w(szComponent),
2780 debugstr_w(szQualifier), dwInstallMode, debugstr_w(szProduct),
2781 Unused1, Unused2, lpPathBuf, pcchPathBuf);
2782
2783 rc = MSIREG_OpenUserComponentsKey(szComponent, &hkey, FALSE);
2784 if (rc != ERROR_SUCCESS)
2785 return ERROR_INDEX_ABSENT;
2786
2787 info = msi_reg_get_val_str( hkey, szQualifier );
2788 RegCloseKey(hkey);
2789
2790 if (!info)
2791 return ERROR_INDEX_ABSENT;
2792
2793 MsiDecomposeDescriptorW(info, product, feature, component, &sz);
2794
2795 if (!szProduct)
2796 rc = MSI_GetComponentPath(product, component, lpPathBuf, pcchPathBuf);
2797 else
2798 rc = MSI_GetComponentPath(szProduct, component, lpPathBuf, pcchPathBuf);
2799
2800 msi_free( info );
2801
2802 if (rc != INSTALLSTATE_LOCAL)
2803 return ERROR_FILE_NOT_FOUND;
2804
2805 return ERROR_SUCCESS;
2806 }
2807
2808 /***********************************************************************
2809 * MsiProvideQualifiedComponentExW [MSI.@]
2810 */
2811 UINT WINAPI MsiProvideQualifiedComponentExW(LPCWSTR szComponent,
2812 LPCWSTR szQualifier, DWORD dwInstallMode, LPCWSTR szProduct,
2813 DWORD Unused1, DWORD Unused2, LPWSTR lpPathBuf,
2814 LPDWORD pcchPathBuf)
2815 {
2816 awstring path;
2817
2818 path.unicode = TRUE;
2819 path.str.w = lpPathBuf;
2820
2821 return MSI_ProvideQualifiedComponentEx(szComponent, szQualifier,
2822 dwInstallMode, szProduct, Unused1, Unused2, &path, pcchPathBuf);
2823 }
2824
2825 /***********************************************************************
2826 * MsiProvideQualifiedComponentExA [MSI.@]
2827 */
2828 UINT WINAPI MsiProvideQualifiedComponentExA(LPCSTR szComponent,
2829 LPCSTR szQualifier, DWORD dwInstallMode, LPCSTR szProduct,
2830 DWORD Unused1, DWORD Unused2, LPSTR lpPathBuf,
2831 LPDWORD pcchPathBuf)
2832 {
2833 LPWSTR szwComponent, szwQualifier = NULL, szwProduct = NULL;
2834 UINT r = ERROR_OUTOFMEMORY;
2835 awstring path;
2836
2837 TRACE("%s %s %u %s %u %u %p %p\n", debugstr_a(szComponent),
2838 debugstr_a(szQualifier), dwInstallMode, debugstr_a(szProduct),
2839 Unused1, Unused2, lpPathBuf, pcchPathBuf);
2840
2841 szwComponent = strdupAtoW( szComponent );
2842 if (szComponent && !szwComponent)
2843 goto end;
2844
2845 szwQualifier = strdupAtoW( szQualifier );
2846 if (szQualifier && !szwQualifier)
2847 goto end;
2848
2849 szwProduct = strdupAtoW( szProduct );
2850 if (szProduct && !szwProduct)
2851 goto end;
2852
2853 path.unicode = FALSE;
2854 path.str.a = lpPathBuf;
2855
2856 r = MSI_ProvideQualifiedComponentEx(szwComponent, szwQualifier,
2857 dwInstallMode, szwProduct, Unused1,
2858 Unused2, &path, pcchPathBuf);
2859 end:
2860 msi_free(szwProduct);
2861 msi_free(szwComponent);
2862 msi_free(szwQualifier);
2863
2864 return r;
2865 }
2866
2867 /***********************************************************************
2868 * MsiProvideQualifiedComponentW [MSI.@]
2869 */
2870 UINT WINAPI MsiProvideQualifiedComponentW( LPCWSTR szComponent,
2871 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR lpPathBuf,
2872 LPDWORD pcchPathBuf)
2873 {
2874 return MsiProvideQualifiedComponentExW(szComponent, szQualifier,
2875 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
2876 }
2877
2878 /***********************************************************************
2879 * MsiProvideQualifiedComponentA [MSI.@]
2880 */
2881 UINT WINAPI MsiProvideQualifiedComponentA( LPCSTR szComponent,
2882 LPCSTR szQualifier, DWORD dwInstallMode, LPSTR lpPathBuf,
2883 LPDWORD pcchPathBuf)
2884 {
2885 return MsiProvideQualifiedComponentExA(szComponent, szQualifier,
2886 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
2887 }
2888
2889 /***********************************************************************
2890 * MSI_GetUserInfo [internal]
2891 */
2892 static USERINFOSTATE MSI_GetUserInfo(LPCWSTR szProduct,
2893 awstring *lpUserNameBuf, LPDWORD pcchUserNameBuf,
2894 awstring *lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
2895 awstring *lpSerialBuf, LPDWORD pcchSerialBuf)
2896 {
2897 WCHAR squished_pc[SQUISH_GUID_SIZE];
2898 LPWSTR user, org, serial;
2899 USERINFOSTATE state;
2900 HKEY hkey, props;
2901 LPCWSTR orgptr;
2902 UINT r;
2903
2904 static const WCHAR szEmpty[] = {0};
2905
2906 TRACE("%s %p %p %p %p %p %p\n", debugstr_w(szProduct), lpUserNameBuf,
2907 pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf,
2908 pcchSerialBuf);
2909
2910 if (!szProduct || !squash_guid(szProduct, squished_pc))
2911 return USERINFOSTATE_INVALIDARG;
2912
2913 if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
2914 &hkey, FALSE) != ERROR_SUCCESS &&
2915 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2916 &hkey, FALSE) != ERROR_SUCCESS &&
2917 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
2918 &hkey, FALSE) != ERROR_SUCCESS)
2919 {
2920 return USERINFOSTATE_UNKNOWN;
2921 }
2922
2923 if (MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
2924 NULL, &props, FALSE) != ERROR_SUCCESS &&
2925 MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE,
2926 NULL, &props, FALSE) != ERROR_SUCCESS)
2927 {
2928 RegCloseKey(hkey);
2929 return USERINFOSTATE_ABSENT;
2930 }
2931
2932 user = msi_reg_get_val_str(props, INSTALLPROPERTY_REGOWNERW);
2933 org = msi_reg_get_val_str(props, INSTALLPROPERTY_REGCOMPANYW);
2934 serial = msi_reg_get_val_str(props, INSTALLPROPERTY_PRODUCTIDW);
2935 state = USERINFOSTATE_ABSENT;
2936
2937 RegCloseKey(hkey);
2938 RegCloseKey(props);
2939
2940 if (user && serial)
2941 state = USERINFOSTATE_PRESENT;
2942
2943 if (pcchUserNameBuf)
2944 {
2945 if (lpUserNameBuf && !user)
2946 {
2947 (*pcchUserNameBuf)--;
2948 goto done;
2949 }
2950
2951 r = msi_strcpy_to_awstring(user, lpUserNameBuf, pcchUserNameBuf);
2952 if (r == ERROR_MORE_DATA)
2953 {
2954 state = USERINFOSTATE_MOREDATA;
2955 goto done;
2956 }
2957 }
2958
2959 if (pcchOrgNameBuf)
2960 {
2961 orgptr = org;
2962 if (!orgptr) orgptr = szEmpty;
2963
2964 r = msi_strcpy_to_awstring(orgptr, lpOrgNameBuf, pcchOrgNameBuf);
2965 if (r == ERROR_MORE_DATA)
2966 {
2967 state = USERINFOSTATE_MOREDATA;
2968 goto done;
2969 }
2970 }
2971
2972 if (pcchSerialBuf)
2973 {
2974 if (!serial)
2975 {
2976 (*pcchSerialBuf)--;
2977 goto done;
2978 }
2979
2980 r = msi_strcpy_to_awstring(serial, lpSerialBuf, pcchSerialBuf);
2981 if (r == ERROR_MORE_DATA)
2982 state = USERINFOSTATE_MOREDATA;
2983 }
2984
2985 done:
2986 msi_free(user);
2987 msi_free(org);
2988 msi_free(serial);
2989
2990 return state;
2991 }
2992
2993 /***********************************************************************
2994 * MsiGetUserInfoW [MSI.@]
2995 */
2996 USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct,
2997 LPWSTR lpUserNameBuf, LPDWORD pcchUserNameBuf,
2998 LPWSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
2999 LPWSTR lpSerialBuf, LPDWORD pcchSerialBuf)
3000 {
3001 awstring user, org, serial;
3002
3003 if ((lpUserNameBuf && !pcchUserNameBuf) ||
3004 (lpOrgNameBuf && !pcchOrgNameBuf) ||
3005 (lpSerialBuf && !pcchSerialBuf))
3006 return USERINFOSTATE_INVALIDARG;
3007
3008 user.unicode = TRUE;
3009 user.str.w = lpUserNameBuf;
3010 org.unicode = TRUE;
3011 org.str.w = lpOrgNameBuf;
3012 serial.unicode = TRUE;
3013 serial.str.w = lpSerialBuf;
3014
3015 return MSI_GetUserInfo( szProduct, &user, pcchUserNameBuf,
3016 &org, pcchOrgNameBuf,
3017 &serial, pcchSerialBuf );
3018 }
3019
3020 USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR szProduct,
3021 LPSTR lpUserNameBuf, LPDWORD pcchUserNameBuf,
3022 LPSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
3023 LPSTR lpSerialBuf, LPDWORD pcchSerialBuf)
3024 {
3025 awstring user, org, serial;
3026 LPWSTR prod;
3027 UINT r;
3028
3029 if ((lpUserNameBuf && !pcchUserNameBuf) ||
3030 (lpOrgNameBuf && !pcchOrgNameBuf) ||
3031 (lpSerialBuf && !pcchSerialBuf))
3032 return USERINFOSTATE_INVALIDARG;
3033
3034 prod = strdupAtoW( szProduct );
3035 if (szProduct && !prod)
3036 return ERROR_OUTOFMEMORY;
3037
3038 user.unicode = FALSE;
3039 user.str.a = lpUserNameBuf;
3040 org.unicode = FALSE;
3041 org.str.a = lpOrgNameBuf;
3042 serial.unicode = FALSE;
3043 serial.str.a = lpSerialBuf;
3044
3045 r = MSI_GetUserInfo( prod, &user, pcchUserNameBuf,
3046 &org, pcchOrgNameBuf,
3047 &serial, pcchSerialBuf );
3048
3049 msi_free( prod );
3050
3051 return r;
3052 }
3053
3054 UINT WINAPI MsiCollectUserInfoW(LPCWSTR szProduct)
3055 {
3056 MSIHANDLE handle;
3057 UINT rc;
3058 MSIPACKAGE *package;
3059 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
3060
3061 TRACE("(%s)\n",debugstr_w(szProduct));
3062
3063 rc = MsiOpenProductW(szProduct,&handle);
3064 if (rc != ERROR_SUCCESS)
3065 return ERROR_INVALID_PARAMETER;
3066
3067 /* MsiCollectUserInfo cannot be called from a custom action. */
3068 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
3069 if (!package)
3070 return ERROR_CALL_NOT_IMPLEMENTED;
3071
3072 rc = ACTION_PerformUIAction(package, szFirstRun, -1);
3073 msiobj_release( &package->hdr );
3074
3075 MsiCloseHandle(handle);
3076
3077 return rc;
3078 }
3079
3080 UINT WINAPI MsiCollectUserInfoA(LPCSTR szProduct)
3081 {
3082 MSIHANDLE handle;
3083 UINT rc;
3084 MSIPACKAGE *package;
3085 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
3086
3087 TRACE("(%s)\n",debugstr_a(szProduct));
3088
3089 rc = MsiOpenProductA(szProduct,&handle);
3090 if (rc != ERROR_SUCCESS)
3091 return ERROR_INVALID_PARAMETER;
3092
3093 /* MsiCollectUserInfo cannot be called from a custom action. */
3094 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
3095 if (!package)
3096 return ERROR_CALL_NOT_IMPLEMENTED;
3097
3098 rc = ACTION_PerformUIAction(package, szFirstRun, -1);
3099 msiobj_release( &package->hdr );
3100
3101 MsiCloseHandle(handle);
3102
3103 return rc;
3104 }
3105
3106 /***********************************************************************
3107 * MsiConfigureFeatureA [MSI.@]
3108 */
3109 UINT WINAPI MsiConfigureFeatureA(LPCSTR szProduct, LPCSTR szFeature, INSTALLSTATE eInstallState)
3110 {
3111 LPWSTR prod, feat = NULL;
3112 UINT r = ERROR_OUTOFMEMORY;
3113
3114 TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature), eInstallState);
3115
3116 prod = strdupAtoW( szProduct );
3117 if (szProduct && !prod)
3118 goto end;
3119
3120 feat = strdupAtoW( szFeature );
3121 if (szFeature && !feat)
3122 goto end;
3123
3124 r = MsiConfigureFeatureW(prod, feat, eInstallState);
3125
3126 end:
3127 msi_free(feat);
3128 msi_free(prod);
3129
3130 return r;
3131 }
3132
3133 /***********************************************************************
3134 * MsiConfigureFeatureW [MSI.@]
3135 */
3136 UINT WINAPI MsiConfigureFeatureW(LPCWSTR szProduct, LPCWSTR szFeature, INSTALLSTATE eInstallState)
3137 {
3138 static const WCHAR szCostInit[] = { 'C','o','s','t','I','n','i','t','i','a','l','i','z','e',0 };
3139 MSIPACKAGE *package = NULL;
3140 UINT r;
3141 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH];
3142 DWORD sz;
3143
3144 TRACE("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature), eInstallState);
3145
3146 if (!szProduct || !szFeature)
3147 return ERROR_INVALID_PARAMETER;
3148
3149 switch (eInstallState)
3150 {
3151 case INSTALLSTATE_DEFAULT:
3152 /* FIXME: how do we figure out the default location? */
3153 eInstallState = INSTALLSTATE_LOCAL;
3154 break;
3155 case INSTALLSTATE_LOCAL:
3156 case INSTALLSTATE_SOURCE:
3157 case INSTALLSTATE_ABSENT:
3158 case INSTALLSTATE_ADVERTISED:
3159 break;
3160 default:
3161 return ERROR_INVALID_PARAMETER;
3162 }
3163
3164 r = MSI_OpenProductW( szProduct, &package );
3165 if (r != ERROR_SUCCESS)
3166 return r;
3167
3168 sz = sizeof(sourcepath);
3169 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3170 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
3171
3172 sz = sizeof(filename);
3173 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3174 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
3175
3176 lstrcatW( sourcepath, filename );
3177
3178 MsiSetInternalUI( INSTALLUILEVEL_BASIC, NULL );
3179
3180 r = ACTION_PerformUIAction( package, szCostInit, -1 );
3181 if (r != ERROR_SUCCESS)
3182 goto end;
3183
3184 r = MSI_SetFeatureStateW( package, szFeature, eInstallState);
3185 if (r != ERROR_SUCCESS)
3186 goto end;
3187
3188 r = MSI_InstallPackage( package, sourcepath, NULL );
3189
3190 end:
3191 msiobj_release( &package->hdr );
3192
3193 return r;
3194 }
3195
3196 /***********************************************************************
3197 * MsiCreateAndVerifyInstallerDirectory [MSI.@]
3198 *
3199 * Notes: undocumented
3200 */
3201 UINT WINAPI MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved)
3202 {
3203 WCHAR path[MAX_PATH];
3204
3205 TRACE("%d\n", dwReserved);
3206
3207 if (dwReserved)
3208 {
3209 FIXME("dwReserved=%d\n", dwReserved);
3210 return ERROR_INVALID_PARAMETER;
3211 }
3212
3213 if (!GetWindowsDirectoryW(path, MAX_PATH))
3214 return ERROR_FUNCTION_FAILED;
3215
3216 lstrcatW(path, installerW);
3217
3218 if (!CreateDirectoryW(path, NULL))
3219 return ERROR_FUNCTION_FAILED;
3220
3221 return ERROR_SUCCESS;
3222 }
3223
3224 /***********************************************************************
3225 * MsiGetShortcutTargetA [MSI.@]
3226 */
3227 UINT WINAPI MsiGetShortcutTargetA( LPCSTR szShortcutTarget,
3228 LPSTR szProductCode, LPSTR szFeatureId,
3229 LPSTR szComponentCode )
3230 {
3231 LPWSTR target;
3232 const int len = MAX_FEATURE_CHARS+1;
3233 WCHAR product[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1], component[MAX_FEATURE_CHARS+1];
3234 UINT r;
3235
3236 target = strdupAtoW( szShortcutTarget );
3237 if (szShortcutTarget && !target )
3238 return ERROR_OUTOFMEMORY;
3239 product[0] = 0;
3240 feature[0] = 0;
3241 component[0] = 0;
3242 r = MsiGetShortcutTargetW( target, product, feature, component );
3243 msi_free( target );
3244 if (r == ERROR_SUCCESS)
3245 {
3246 WideCharToMultiByte( CP_ACP, 0, product, -1, szProductCode, len, NULL, NULL );
3247 WideCharToMultiByte( CP_ACP, 0, feature, -1, szFeatureId, len, NULL, NULL );
3248 WideCharToMultiByte( CP_ACP, 0, component, -1, szComponentCode, len, NULL, NULL );
3249 }
3250 return r;
3251 }
3252
3253 /***********************************************************************
3254 * MsiGetShortcutTargetW [MSI.@]
3255 */
3256 UINT WINAPI MsiGetShortcutTargetW( LPCWSTR szShortcutTarget,
3257 LPWSTR szProductCode, LPWSTR szFeatureId,
3258 LPWSTR szComponentCode )
3259 {
3260 IShellLinkDataList *dl = NULL;
3261 IPersistFile *pf = NULL;
3262 LPEXP_DARWIN_LINK darwin = NULL;
3263 HRESULT r, init;
3264
3265 TRACE("%s %p %p %p\n", debugstr_w(szShortcutTarget),
3266 szProductCode, szFeatureId, szComponentCode );
3267
3268 init = CoInitialize(NULL);
3269
3270 r = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
3271 &IID_IPersistFile, (LPVOID*) &pf );
3272 if( SUCCEEDED( r ) )
3273 {
3274 r = IPersistFile_Load( pf, szShortcutTarget,
3275 STGM_READ | STGM_SHARE_DENY_WRITE );
3276 if( SUCCEEDED( r ) )
3277 {
3278 r = IPersistFile_QueryInterface( pf, &IID_IShellLinkDataList,
3279 (LPVOID*) &dl );
3280 if( SUCCEEDED( r ) )
3281 {
3282 IShellLinkDataList_CopyDataBlock( dl, EXP_DARWIN_ID_SIG,
3283 (LPVOID) &darwin );
3284 IShellLinkDataList_Release( dl );
3285 }
3286 }
3287 IPersistFile_Release( pf );
3288 }
3289
3290 if (SUCCEEDED(init))
3291 CoUninitialize();
3292
3293 TRACE("darwin = %p\n", darwin);
3294
3295 if (darwin)
3296 {
3297 DWORD sz;
3298 UINT ret;
3299
3300 ret = MsiDecomposeDescriptorW( darwin->szwDarwinID,
3301 szProductCode, szFeatureId, szComponentCode, &sz );
3302 LocalFree( darwin );
3303 return ret;
3304 }
3305
3306 return ERROR_FUNCTION_FAILED;
3307 }
3308
3309 UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature,
3310 DWORD dwReinstallMode )
3311 {
3312 MSIPACKAGE* package = NULL;
3313 UINT r;
3314 WCHAR sourcepath[MAX_PATH];
3315 WCHAR filename[MAX_PATH];
3316 static const WCHAR szLogVerbose[] = {
3317 ' ','L','O','G','V','E','R','B','O','S','E',0 };
3318 static const WCHAR szInstalled[] = { 'I','n','s','t','a','l','l','e','d',0};
3319 static const WCHAR szReinstall[] = {'R','E','I','N','S','T','A','L','L',0};
3320 static const WCHAR szReinstallMode[] = {'R','E','I','N','S','T','A','L','L','M','O','D','E',0};
3321 static const WCHAR szOne[] = {'1',0};
3322 WCHAR reinstallmode[11];
3323 LPWSTR ptr;
3324 DWORD sz;
3325
3326 FIXME("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature),
3327 dwReinstallMode);
3328
3329 ptr = reinstallmode;
3330
3331 if (dwReinstallMode & REINSTALLMODE_FILEMISSING)
3332 *ptr++ = 'p';
3333 if (dwReinstallMode & REINSTALLMODE_FILEOLDERVERSION)
3334 *ptr++ = 'o';
3335 if (dwReinstallMode & REINSTALLMODE_FILEEQUALVERSION)
3336 *ptr++ = 'w';
3337 if (dwReinstallMode & REINSTALLMODE_FILEEXACT)
3338 *ptr++ = 'd';
3339 if (dwReinstallMode & REINSTALLMODE_FILEVERIFY)
3340 *ptr++ = 'c';
3341 if (dwReinstallMode & REINSTALLMODE_FILEREPLACE)
3342 *ptr++ = 'a';
3343 if (dwReinstallMode & REINSTALLMODE_USERDATA)
3344 *ptr++ = 'u';
3345 if (dwReinstallMode & REINSTALLMODE_MACHINEDATA)
3346 *ptr++ = 'm';
3347 if (dwReinstallMode & REINSTALLMODE_SHORTCUT)
3348 *ptr++ = 's';
3349 if (dwReinstallMode & REINSTALLMODE_PACKAGE)
3350 *ptr++ = 'v';
3351 *ptr = 0;
3352
3353 sz = sizeof(sourcepath);
3354 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3355 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
3356
3357 sz = sizeof(filename);
3358 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3359 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
3360
3361 lstrcatW( sourcepath, filename );
3362
3363 if (dwReinstallMode & REINSTALLMODE_PACKAGE)
3364 r = MSI_OpenPackageW( sourcepath, &package );
3365 else
3366 r = MSI_OpenProductW( szProduct, &package );
3367
3368 if (r != ERROR_SUCCESS)
3369 return r;
3370
3371 MSI_SetPropertyW( package, szReinstallMode, reinstallmode );
3372 MSI_SetPropertyW( package, szInstalled, szOne );
3373 MSI_SetPropertyW( package, szLogVerbose, szOne );
3374 MSI_SetPropertyW( package, szReinstall, szFeature );
3375
3376 r = MSI_InstallPackage( package, sourcepath, NULL );
3377
3378 msiobj_release( &package->hdr );
3379
3380 return r;
3381 }
3382
3383 UINT WINAPI MsiReinstallFeatureA( LPCSTR szProduct, LPCSTR szFeature,
3384 DWORD dwReinstallMode )
3385 {
3386 LPWSTR wszProduct;
3387 LPWSTR wszFeature;
3388 UINT rc;
3389
3390 TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature),
3391 dwReinstallMode);
3392
3393 wszProduct = strdupAtoW(szProduct);
3394 wszFeature = strdupAtoW(szFeature);
3395
3396 rc = MsiReinstallFeatureW(wszProduct, wszFeature, dwReinstallMode);
3397
3398 msi_free(wszProduct);
3399 msi_free(wszFeature);
3400 return rc;
3401 }
3402
3403 typedef struct
3404 {
3405 unsigned int i[2];
3406 unsigned int buf[4];
3407 unsigned char in[64];
3408 unsigned char digest[16];
3409 } MD5_CTX;
3410
3411 extern VOID WINAPI MD5Init( MD5_CTX *);
3412 extern VOID WINAPI MD5Update( MD5_CTX *, const unsigned char *, unsigned int );
3413 extern VOID WINAPI MD5Final( MD5_CTX *);
3414
3415 /***********************************************************************
3416 * MsiGetFileHashW [MSI.@]
3417 */
3418 UINT WINAPI MsiGetFileHashW( LPCWSTR szFilePath, DWORD dwOptions,
3419 PMSIFILEHASHINFO pHash )
3420 {
3421 HANDLE handle, mapping;
3422 void *p;
3423 DWORD length;
3424 UINT r = ERROR_FUNCTION_FAILED;
3425
3426 TRACE("%s %08x %p\n", debugstr_w(szFilePath), dwOptions, pHash );
3427
3428 if (!szFilePath)
3429 return ERROR_INVALID_PARAMETER;
3430
3431 if (!*szFilePath)
3432 return ERROR_PATH_NOT_FOUND;
3433
3434 if (dwOptions)
3435 return ERROR_INVALID_PARAMETER;
3436 if (!pHash)
3437 return ERROR_INVALID_PARAMETER;
3438 if (pHash->dwFileHashInfoSize < sizeof *pHash)
3439 return ERROR_INVALID_PARAMETER;
3440
3441 handle = CreateFileW( szFilePath, GENERIC_READ,
3442 FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL );
3443 if (handle == INVALID_HANDLE_VALUE)
3444 return ERROR_FILE_NOT_FOUND;
3445
3446 length = GetFileSize( handle, NULL );
3447
3448 mapping = CreateFileMappingW( handle, NULL, PAGE_READONLY, 0, 0, NULL );
3449 if (mapping)
3450 {
3451 p = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, length );
3452 if (p)
3453 {
3454 MD5_CTX ctx;
3455
3456 MD5Init( &ctx );
3457 MD5Update( &ctx, p, length );
3458 MD5Final( &ctx );
3459 UnmapViewOfFile( p );
3460
3461 memcpy( pHash->dwData, ctx.digest, sizeof pHash->dwData );
3462 r = ERROR_SUCCESS;
3463 }
3464 CloseHandle( mapping );
3465 }
3466 CloseHandle( handle );
3467
3468 return r;
3469 }
3470
3471 /***********************************************************************
3472 * MsiGetFileHashA [MSI.@]
3473 */
3474 UINT WINAPI MsiGetFileHashA( LPCSTR szFilePath, DWORD dwOptions,
3475 PMSIFILEHASHINFO pHash )
3476 {
3477 LPWSTR file;
3478 UINT r;
3479
3480 TRACE("%s %08x %p\n", debugstr_a(szFilePath), dwOptions, pHash );
3481
3482 file = strdupAtoW( szFilePath );
3483 if (szFilePath && !file)
3484 return ERROR_OUTOFMEMORY;
3485
3486 r = MsiGetFileHashW( file, dwOptions, pHash );
3487 msi_free( file );
3488 return r;
3489 }
3490
3491 /***********************************************************************
3492 * MsiAdvertiseScriptW [MSI.@]
3493 */
3494 UINT WINAPI MsiAdvertiseScriptW( LPCWSTR szScriptFile, DWORD dwFlags,
3495 PHKEY phRegData, BOOL fRemoveItems )
3496 {
3497 FIXME("%s %08x %p %d\n",
3498 debugstr_w( szScriptFile ), dwFlags, phRegData, fRemoveItems );
3499 return ERROR_CALL_NOT_IMPLEMENTED;
3500 }
3501
3502 /***********************************************************************
3503 * MsiAdvertiseScriptA [MSI.@]
3504 */
3505 UINT WINAPI MsiAdvertiseScriptA( LPCSTR szScriptFile, DWORD dwFlags,
3506 PHKEY phRegData, BOOL fRemoveItems )
3507 {
3508 FIXME("%s %08x %p %d\n",
3509 debugstr_a( szScriptFile ), dwFlags, phRegData, fRemoveItems );
3510 return ERROR_CALL_NOT_IMPLEMENTED;
3511 }
3512
3513 /***********************************************************************
3514 * MsiIsProductElevatedW [MSI.@]
3515 */
3516 UINT WINAPI MsiIsProductElevatedW( LPCWSTR szProduct, BOOL *pfElevated )
3517 {
3518 FIXME("%s %p - stub\n",
3519 debugstr_w( szProduct ), pfElevated );
3520 *pfElevated = TRUE;
3521 return ERROR_SUCCESS;
3522 }
3523
3524 /***********************************************************************
3525 * MsiIsProductElevatedA [MSI.@]
3526 */
3527 UINT WINAPI MsiIsProductElevatedA( LPCSTR szProduct, BOOL *pfElevated )
3528 {
3529 FIXME("%s %p - stub\n",
3530 debugstr_a( szProduct ), pfElevated );
3531 *pfElevated = TRUE;
3532 return ERROR_SUCCESS;
3533 }
3534
3535 /***********************************************************************
3536 * MsiSetExternalUIRecord [MSI.@]
3537 */
3538 UINT WINAPI MsiSetExternalUIRecord( INSTALLUI_HANDLER_RECORD puiHandler,
3539 DWORD dwMessageFilter, LPVOID pvContext,
3540 PINSTALLUI_HANDLER_RECORD ppuiPrevHandler)
3541 {
3542 FIXME("%p %08x %p %p\n", puiHandler, dwMessageFilter ,pvContext,
3543 ppuiPrevHandler);
3544 return ERROR_CALL_NOT_IMPLEMENTED;
3545 }
3546
3547 /***********************************************************************
3548 * MsiInstallMissingComponentW [MSI.@]
3549 */
3550 UINT WINAPI MsiInstallMissingComponentW(LPCWSTR szProduct, LPCWSTR szComponent, INSTALLSTATE eInstallState)
3551 {
3552 FIXME("(%s %s %d\n", debugstr_w(szProduct), debugstr_w(szComponent), eInstallState);
3553 return ERROR_SUCCESS;
3554 }