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