msi: Add a stub implementation of MsiQueryComponentStateA.
[wine/multimedia.git] / dlls / msi / msi.c
blob2042695ef6af8d4cbf013a01b48473cf72d3c93e
1 /*
2 * Implementation of the Microsoft Installer (msi.dll)
4 * Copyright 2002,2003,2004,2005 Mike McCormack for CodeWeavers
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.
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.
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
21 #include <stdarg.h>
23 #define COBJMACROS
24 #define NONAMELESSUNION
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"
44 WINE_DEFAULT_DEBUG_CHANNEL(msi);
46 static const WCHAR installerW[] = {'\\','I','n','s','t','a','l','l','e','r',0};
48 UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct)
50 UINT r;
51 LPWSTR szwProd = NULL;
53 TRACE("%s %p\n",debugstr_a(szProduct), phProduct);
55 if( szProduct )
57 szwProd = strdupAtoW( szProduct );
58 if( !szwProd )
59 return ERROR_OUTOFMEMORY;
62 r = MsiOpenProductW( szwProd, phProduct );
64 msi_free( szwProd );
66 return r;
69 static UINT MSI_OpenProductW( LPCWSTR szProduct, MSIPACKAGE **ppackage )
71 LPWSTR path = NULL;
72 UINT r;
73 HKEY hKeyProduct = NULL;
74 DWORD count, type;
76 TRACE("%s %p\n", debugstr_w(szProduct), ppackage );
78 r = MSIREG_OpenUninstallKey(szProduct,&hKeyProduct,FALSE);
79 if( r != ERROR_SUCCESS )
81 r = ERROR_UNKNOWN_PRODUCT;
82 goto end;
85 /* find the size of the path */
86 type = count = 0;
87 r = RegQueryValueExW( hKeyProduct, INSTALLPROPERTY_LOCALPACKAGEW,
88 NULL, &type, NULL, &count );
89 if( r != ERROR_SUCCESS )
91 r = ERROR_UNKNOWN_PRODUCT;
92 goto end;
95 /* now alloc and fetch the path of the database to open */
96 path = msi_alloc( count );
97 if( !path )
98 goto end;
100 r = RegQueryValueExW( hKeyProduct, INSTALLPROPERTY_LOCALPACKAGEW,
101 NULL, &type, (LPBYTE) path, &count );
102 if( r != ERROR_SUCCESS )
104 r = ERROR_UNKNOWN_PRODUCT;
105 goto end;
108 r = MSI_OpenPackageW( path, ppackage );
110 end:
111 msi_free( path );
112 if( hKeyProduct )
113 RegCloseKey( hKeyProduct );
115 return r;
118 UINT WINAPI MsiOpenProductW( LPCWSTR szProduct, MSIHANDLE *phProduct )
120 MSIPACKAGE *package = NULL;
121 UINT r;
123 r = MSI_OpenProductW( szProduct, &package );
124 if( r == ERROR_SUCCESS )
126 *phProduct = alloc_msihandle( &package->hdr );
127 if (! *phProduct)
128 r = ERROR_NOT_ENOUGH_MEMORY;
129 msiobj_release( &package->hdr );
131 return r;
134 UINT WINAPI MsiAdvertiseProductA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
135 LPCSTR szTransforms, LANGID lgidLanguage)
137 FIXME("%s %s %s %08x\n",debugstr_a(szPackagePath),
138 debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage);
139 return ERROR_CALL_NOT_IMPLEMENTED;
142 UINT WINAPI MsiAdvertiseProductW(LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
143 LPCWSTR szTransforms, LANGID lgidLanguage)
145 FIXME("%s %s %s %08x\n",debugstr_w(szPackagePath),
146 debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage);
147 return ERROR_CALL_NOT_IMPLEMENTED;
150 UINT WINAPI MsiAdvertiseProductExA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
151 LPCSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
153 FIXME("%s %s %s %08x %08x %08x\n", debugstr_a(szPackagePath),
154 debugstr_a(szScriptfilePath), debugstr_a(szTransforms),
155 lgidLanguage, dwPlatform, dwOptions);
156 return ERROR_CALL_NOT_IMPLEMENTED;
159 UINT WINAPI MsiAdvertiseProductExW( LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
160 LPCWSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
162 FIXME("%s %s %s %08x %08x %08x\n", debugstr_w(szPackagePath),
163 debugstr_w(szScriptfilePath), debugstr_w(szTransforms),
164 lgidLanguage, dwPlatform, dwOptions);
165 return ERROR_CALL_NOT_IMPLEMENTED;
168 UINT WINAPI MsiInstallProductA(LPCSTR szPackagePath, LPCSTR szCommandLine)
170 LPWSTR szwPath = NULL, szwCommand = NULL;
171 UINT r = ERROR_OUTOFMEMORY;
173 TRACE("%s %s\n",debugstr_a(szPackagePath), debugstr_a(szCommandLine));
175 if( szPackagePath )
177 szwPath = strdupAtoW( szPackagePath );
178 if( !szwPath )
179 goto end;
182 if( szCommandLine )
184 szwCommand = strdupAtoW( szCommandLine );
185 if( !szwCommand )
186 goto end;
189 r = MsiInstallProductW( szwPath, szwCommand );
191 end:
192 msi_free( szwPath );
193 msi_free( szwCommand );
195 return r;
198 UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
200 MSIPACKAGE *package = NULL;
201 UINT r;
203 TRACE("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine));
205 r = MSI_OpenPackageW( szPackagePath, &package );
206 if (r == ERROR_SUCCESS)
208 r = MSI_InstallPackage( package, szPackagePath, szCommandLine );
209 msiobj_release( &package->hdr );
212 return r;
215 UINT WINAPI MsiReinstallProductA(LPCSTR szProduct, DWORD dwReinstallMode)
217 FIXME("%s %08x\n", debugstr_a(szProduct), dwReinstallMode);
218 return ERROR_CALL_NOT_IMPLEMENTED;
221 UINT WINAPI MsiReinstallProductW(LPCWSTR szProduct, DWORD dwReinstallMode)
223 FIXME("%s %08x\n", debugstr_w(szProduct), dwReinstallMode);
224 return ERROR_CALL_NOT_IMPLEMENTED;
227 UINT WINAPI MsiApplyPatchA(LPCSTR szPatchPackage, LPCSTR szInstallPackage,
228 INSTALLTYPE eInstallType, LPCSTR szCommandLine)
230 LPWSTR patch_package = NULL;
231 LPWSTR install_package = NULL;
232 LPWSTR command_line = NULL;
233 UINT r = ERROR_OUTOFMEMORY;
235 TRACE("%s %s %d %s\n", debugstr_a(szPatchPackage), debugstr_a(szInstallPackage),
236 eInstallType, debugstr_a(szCommandLine));
238 if (szPatchPackage && !(patch_package = strdupAtoW(szPatchPackage)))
239 goto done;
241 if (szInstallPackage && !(install_package = strdupAtoW(szInstallPackage)))
242 goto done;
244 if (szCommandLine && !(command_line = strdupAtoW(szCommandLine)))
245 goto done;
247 r = MsiApplyPatchW(patch_package, install_package, eInstallType, command_line);
249 done:
250 msi_free(patch_package);
251 msi_free(install_package);
252 msi_free(command_line);
254 return r;
257 UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage,
258 INSTALLTYPE eInstallType, LPCWSTR szCommandLine)
260 MSIHANDLE patch, info;
261 UINT r, type;
262 DWORD size = 0;
263 LPCWSTR cmd_ptr = szCommandLine;
264 LPWSTR beg, end;
265 LPWSTR cmd = NULL, codes = NULL;
267 static const WCHAR space[] = {' ',0};
268 static const WCHAR patcheq[] = {'P','A','T','C','H','=',0};
269 static WCHAR empty[] = {0};
271 TRACE("%s %s %d %s\n", debugstr_w(szPatchPackage), debugstr_w(szInstallPackage),
272 eInstallType, debugstr_w(szCommandLine));
274 if (szInstallPackage || eInstallType == INSTALLTYPE_NETWORK_IMAGE ||
275 eInstallType == INSTALLTYPE_SINGLE_INSTANCE)
277 FIXME("Only reading target products from patch\n");
278 return ERROR_CALL_NOT_IMPLEMENTED;
281 r = MsiOpenDatabaseW(szPatchPackage, MSIDBOPEN_READONLY, &patch);
282 if (r != ERROR_SUCCESS)
283 return r;
285 r = MsiGetSummaryInformationW(patch, NULL, 0, &info);
286 if (r != ERROR_SUCCESS)
287 goto done;
289 r = MsiSummaryInfoGetPropertyW(info, PID_TEMPLATE, &type, NULL, NULL, empty, &size);
290 if (r != ERROR_MORE_DATA || !size || type != VT_LPSTR)
292 ERR("Failed to read product codes from patch\n");
293 goto done;
296 codes = msi_alloc(++size * sizeof(WCHAR));
297 if (!codes)
299 r = ERROR_OUTOFMEMORY;
300 goto done;
303 r = MsiSummaryInfoGetPropertyW(info, PID_TEMPLATE, &type, NULL, NULL, codes, &size);
304 if (r != ERROR_SUCCESS)
305 goto done;
307 if (!szCommandLine)
308 cmd_ptr = empty;
310 size = lstrlenW(cmd_ptr) + lstrlenW(patcheq) + lstrlenW(szPatchPackage) + 1;
311 cmd = msi_alloc(size * sizeof(WCHAR));
312 if (!cmd)
314 r = ERROR_OUTOFMEMORY;
315 goto done;
318 lstrcpyW(cmd, cmd_ptr);
319 if (szCommandLine) lstrcatW(cmd, space);
320 lstrcatW(cmd, patcheq);
321 lstrcatW(cmd, szPatchPackage);
323 beg = codes;
324 while ((end = strchrW(beg, '}')))
326 *(end + 1) = '\0';
328 r = MsiConfigureProductExW(beg, INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd);
329 if (r != ERROR_SUCCESS)
330 goto done;
332 beg = end + 2;
335 done:
336 msi_free(cmd);
337 msi_free(codes);
339 MsiCloseHandle(info);
340 MsiCloseHandle(patch);
342 return r;
345 UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
346 INSTALLSTATE eInstallState, LPCWSTR szCommandLine)
348 MSIPACKAGE* package = NULL;
349 UINT r;
350 DWORD sz;
351 WCHAR sourcepath[MAX_PATH];
352 WCHAR filename[MAX_PATH];
353 static const WCHAR szInstalled[] = {
354 ' ','I','n','s','t','a','l','l','e','d','=','1',0};
355 LPWSTR commandline;
357 TRACE("%s %d %d %s\n",debugstr_w(szProduct), iInstallLevel, eInstallState,
358 debugstr_w(szCommandLine));
360 if (eInstallState != INSTALLSTATE_LOCAL &&
361 eInstallState != INSTALLSTATE_DEFAULT)
363 FIXME("Not implemented for anything other than local installs\n");
364 return ERROR_CALL_NOT_IMPLEMENTED;
367 sz = sizeof(sourcepath);
368 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
369 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath,
370 &sz);
372 sz = sizeof(filename);
373 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
374 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
376 lstrcatW(sourcepath,filename);
379 * ok 1, we need to find the msi file for this product.
380 * 2, find the source dir for the files
381 * 3, do the configure/install.
382 * 4, cleanupany runonce entry.
385 r = MSI_OpenProductW( szProduct, &package );
386 if (r != ERROR_SUCCESS)
387 return r;
389 sz = lstrlenW(szInstalled) + 1;
391 if (szCommandLine)
392 sz += lstrlenW(szCommandLine);
394 commandline = msi_alloc(sz * sizeof(WCHAR));
395 if (!commandline )
397 r = ERROR_OUTOFMEMORY;
398 goto end;
401 commandline[0] = 0;
402 if (szCommandLine)
403 lstrcpyW(commandline,szCommandLine);
405 if (MsiQueryProductStateW(szProduct) != INSTALLSTATE_UNKNOWN)
406 lstrcatW(commandline,szInstalled);
408 r = MSI_InstallPackage( package, sourcepath, commandline );
410 msi_free(commandline);
412 end:
413 msiobj_release( &package->hdr );
415 return r;
418 UINT WINAPI MsiConfigureProductExA(LPCSTR szProduct, int iInstallLevel,
419 INSTALLSTATE eInstallState, LPCSTR szCommandLine)
421 LPWSTR szwProduct = NULL;
422 LPWSTR szwCommandLine = NULL;
423 UINT r = ERROR_OUTOFMEMORY;
425 if( szProduct )
427 szwProduct = strdupAtoW( szProduct );
428 if( !szwProduct )
429 goto end;
432 if( szCommandLine)
434 szwCommandLine = strdupAtoW( szCommandLine );
435 if( !szwCommandLine)
436 goto end;
439 r = MsiConfigureProductExW( szwProduct, iInstallLevel, eInstallState,
440 szwCommandLine );
441 end:
442 msi_free( szwProduct );
443 msi_free( szwCommandLine);
445 return r;
448 UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel,
449 INSTALLSTATE eInstallState)
451 LPWSTR szwProduct = NULL;
452 UINT r;
454 TRACE("%s %d %d\n",debugstr_a(szProduct), iInstallLevel, eInstallState);
456 if( szProduct )
458 szwProduct = strdupAtoW( szProduct );
459 if( !szwProduct )
460 return ERROR_OUTOFMEMORY;
463 r = MsiConfigureProductW( szwProduct, iInstallLevel, eInstallState );
464 msi_free( szwProduct );
466 return r;
469 UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel,
470 INSTALLSTATE eInstallState)
472 return MsiConfigureProductExW(szProduct, iInstallLevel, eInstallState, NULL);
475 UINT WINAPI MsiGetProductCodeA(LPCSTR szComponent, LPSTR szBuffer)
477 LPWSTR szwComponent = NULL;
478 UINT r;
479 WCHAR szwBuffer[GUID_SIZE];
481 TRACE("%s %s\n",debugstr_a(szComponent), debugstr_a(szBuffer));
483 if( szComponent )
485 szwComponent = strdupAtoW( szComponent );
486 if( !szwComponent )
487 return ERROR_OUTOFMEMORY;
490 r = MsiGetProductCodeW( szwComponent, szwBuffer );
492 if( ERROR_SUCCESS == r )
493 WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, GUID_SIZE, NULL, NULL);
495 msi_free( szwComponent );
497 return r;
500 UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer)
502 UINT rc;
503 HKEY hkey;
504 WCHAR szSquished[GUID_SIZE];
505 DWORD sz = GUID_SIZE;
506 static const WCHAR szPermKey[] =
507 { '0','0','0','0','0','0','0','0','0','0','0','0',
508 '0','0','0','0','0','0','0','0','0','0','0','0',
509 '0','0','0','0','0','0','0','0',0};
511 TRACE("%s %p\n",debugstr_w(szComponent), szBuffer);
513 if (NULL == szComponent)
514 return ERROR_INVALID_PARAMETER;
516 rc = MSIREG_OpenComponentsKey( szComponent, &hkey, FALSE);
517 if (rc != ERROR_SUCCESS)
518 return ERROR_UNKNOWN_COMPONENT;
520 rc = RegEnumValueW(hkey, 0, szSquished, &sz, NULL, NULL, NULL, NULL);
521 if (rc == ERROR_SUCCESS && strcmpW(szSquished,szPermKey)==0)
523 sz = GUID_SIZE;
524 rc = RegEnumValueW(hkey, 1, szSquished, &sz, NULL, NULL, NULL, NULL);
527 RegCloseKey(hkey);
529 if (rc != ERROR_SUCCESS)
530 return ERROR_INSTALL_FAILURE;
532 unsquash_guid(szSquished, szBuffer);
533 return ERROR_SUCCESS;
536 static UINT WINAPI MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
537 awstring *szValue, DWORD *pcchValueBuf)
539 UINT r;
540 HKEY hkey;
541 LPWSTR val = NULL;
543 TRACE("%s %s %p %p\n", debugstr_w(szProduct),
544 debugstr_w(szAttribute), szValue, pcchValueBuf);
547 * FIXME: Values seem scattered/duplicated in the registry. Is there a system?
550 if ((szValue->str.w && !pcchValueBuf) || !szProduct || !szProduct[0] || !szAttribute)
551 return ERROR_INVALID_PARAMETER;
553 /* check for special properties */
554 if (!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW))
556 LPWSTR regval;
557 WCHAR packagecode[35];
559 r = MSIREG_OpenUserProductsKey(szProduct, &hkey, FALSE);
560 if (r != ERROR_SUCCESS)
561 return ERROR_UNKNOWN_PRODUCT;
563 regval = msi_reg_get_val_str( hkey, szAttribute );
564 if (regval)
566 if (unsquash_guid(regval, packagecode))
567 val = strdupW(packagecode);
568 msi_free(regval);
571 RegCloseKey(hkey);
573 else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW))
575 static const WCHAR one[] = { '1',0 };
577 * FIXME: should be in the Product key (user or system?)
578 * but isn't written yet...
580 val = strdupW( one );
582 else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_LANGUAGEW) ||
583 !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONW))
585 static const WCHAR fmt[] = { '%','u',0 };
586 WCHAR szVal[16];
587 DWORD regval;
589 r = MSIREG_OpenUninstallKey(szProduct, &hkey, FALSE);
590 if (r != ERROR_SUCCESS)
591 return ERROR_UNKNOWN_PRODUCT;
593 if (msi_reg_get_val_dword( hkey, szAttribute, &regval))
595 sprintfW(szVal, fmt, regval);
596 val = strdupW( szVal );
599 RegCloseKey(hkey);
601 else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTNAMEW))
603 r = MSIREG_OpenUserProductsKey(szProduct, &hkey, FALSE);
604 if (r != ERROR_SUCCESS)
605 return ERROR_UNKNOWN_PRODUCT;
607 val = msi_reg_get_val_str( hkey, szAttribute );
609 RegCloseKey(hkey);
611 else if (!szAttribute[0])
613 return ERROR_UNKNOWN_PROPERTY;
615 else
617 static const WCHAR szDisplayVersion[] = {
618 'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0 };
620 FIXME("%s\n", debugstr_w(szAttribute));
621 /* FIXME: some attribute values not tested... */
623 if (!lstrcmpW( szAttribute, INSTALLPROPERTY_VERSIONSTRINGW ))
624 szAttribute = szDisplayVersion;
626 r = MSIREG_OpenUninstallKey( szProduct, &hkey, FALSE );
627 if (r != ERROR_SUCCESS)
628 return ERROR_UNKNOWN_PRODUCT;
630 val = msi_reg_get_val_str( hkey, szAttribute );
632 RegCloseKey(hkey);
635 TRACE("returning %s\n", debugstr_w(val));
637 if (!val)
638 return ERROR_UNKNOWN_PROPERTY;
640 r = msi_strcpy_to_awstring( val, szValue, pcchValueBuf );
642 msi_free(val);
644 return r;
647 UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute,
648 LPSTR szBuffer, DWORD *pcchValueBuf)
650 LPWSTR szwProduct, szwAttribute = NULL;
651 UINT r = ERROR_OUTOFMEMORY;
652 awstring buffer;
654 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szAttribute),
655 szBuffer, pcchValueBuf);
657 szwProduct = strdupAtoW( szProduct );
658 if( szProduct && !szwProduct )
659 goto end;
661 szwAttribute = strdupAtoW( szAttribute );
662 if( szAttribute && !szwAttribute )
663 goto end;
665 buffer.unicode = FALSE;
666 buffer.str.a = szBuffer;
668 r = MSI_GetProductInfo( szwProduct, szwAttribute,
669 &buffer, pcchValueBuf );
671 end:
672 msi_free( szwProduct );
673 msi_free( szwAttribute );
675 return r;
678 UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute,
679 LPWSTR szBuffer, DWORD *pcchValueBuf)
681 awstring buffer;
683 TRACE("%s %s %p %p\n", debugstr_w(szProduct), debugstr_w(szAttribute),
684 szBuffer, pcchValueBuf);
686 buffer.unicode = TRUE;
687 buffer.str.w = szBuffer;
689 return MSI_GetProductInfo( szProduct, szAttribute,
690 &buffer, pcchValueBuf );
693 UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes)
695 LPWSTR szwLogFile = NULL;
696 UINT r;
698 TRACE("%08x %s %08x\n", dwLogMode, debugstr_a(szLogFile), attributes);
700 if( szLogFile )
702 szwLogFile = strdupAtoW( szLogFile );
703 if( !szwLogFile )
704 return ERROR_OUTOFMEMORY;
706 r = MsiEnableLogW( dwLogMode, szwLogFile, attributes );
707 msi_free( szwLogFile );
708 return r;
711 UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, DWORD attributes)
713 HANDLE file = INVALID_HANDLE_VALUE;
715 TRACE("%08x %s %08x\n", dwLogMode, debugstr_w(szLogFile), attributes);
717 if (szLogFile)
719 lstrcpyW(gszLogFile,szLogFile);
720 if (!(attributes & INSTALLLOGATTRIBUTES_APPEND))
721 DeleteFileW(szLogFile);
722 file = CreateFileW(szLogFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
723 FILE_ATTRIBUTE_NORMAL, NULL);
724 if (file != INVALID_HANDLE_VALUE)
725 CloseHandle(file);
726 else
727 ERR("Unable to enable log %s\n",debugstr_w(szLogFile));
729 else
730 gszLogFile[0] = '\0';
732 return ERROR_SUCCESS;
735 UINT WINAPI MsiQueryComponentStateA(LPSTR szProductCode, LPSTR szUserSid, MSIINSTALLCONTEXT dwContext, LPCSTR szComponent, INSTALLSTATE *pdwState)
737 FIXME("(%s, %s, %d, %s, %p): stub!\n", debugstr_a(szProductCode), debugstr_a(szUserSid), dwContext, debugstr_a(szComponent), pdwState);
739 if (!pdwState)
740 return ERROR_INVALID_PARAMETER;
742 *pdwState = INSTALLSTATE_UNKNOWN;
743 return ERROR_UNKNOWN_PRODUCT;
746 INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct)
748 LPWSTR szwProduct = NULL;
749 INSTALLSTATE r;
751 if( szProduct )
753 szwProduct = strdupAtoW( szProduct );
754 if( !szwProduct )
755 return ERROR_OUTOFMEMORY;
757 r = MsiQueryProductStateW( szwProduct );
758 msi_free( szwProduct );
759 return r;
762 INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct)
764 UINT rc;
765 INSTALLSTATE rrc = INSTALLSTATE_UNKNOWN;
766 HKEY hkey = 0;
767 static const WCHAR szWindowsInstaller[] = {
768 'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0 };
769 DWORD sz;
771 TRACE("%s\n", debugstr_w(szProduct));
773 if (!szProduct)
774 return INSTALLSTATE_INVALIDARG;
776 rc = MSIREG_OpenUserProductsKey(szProduct,&hkey,FALSE);
777 if (rc != ERROR_SUCCESS)
778 goto end;
780 RegCloseKey(hkey);
782 rc = MSIREG_OpenUninstallKey(szProduct,&hkey,FALSE);
783 if (rc != ERROR_SUCCESS)
784 goto end;
786 sz = sizeof(rrc);
787 rc = RegQueryValueExW(hkey,szWindowsInstaller,NULL,NULL,(LPVOID)&rrc, &sz);
788 if (rc != ERROR_SUCCESS)
789 goto end;
791 switch (rrc)
793 case 1:
794 /* default */
795 rrc = INSTALLSTATE_DEFAULT;
796 break;
797 default:
798 FIXME("Unknown install state read from registry (%i)\n",rrc);
799 rrc = INSTALLSTATE_UNKNOWN;
800 break;
802 end:
803 RegCloseKey(hkey);
804 return rrc;
807 INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd)
809 INSTALLUILEVEL old = gUILevel;
810 HWND oldwnd = gUIhwnd;
812 TRACE("%08x %p\n", dwUILevel, phWnd);
814 gUILevel = dwUILevel;
815 if (phWnd)
817 gUIhwnd = *phWnd;
818 *phWnd = oldwnd;
820 return old;
823 INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler,
824 DWORD dwMessageFilter, LPVOID pvContext)
826 INSTALLUI_HANDLERA prev = gUIHandlerA;
828 TRACE("%p %x %p\n",puiHandler, dwMessageFilter,pvContext);
829 gUIHandlerA = puiHandler;
830 gUIFilter = dwMessageFilter;
831 gUIContext = pvContext;
833 return prev;
836 INSTALLUI_HANDLERW WINAPI MsiSetExternalUIW(INSTALLUI_HANDLERW puiHandler,
837 DWORD dwMessageFilter, LPVOID pvContext)
839 INSTALLUI_HANDLERW prev = gUIHandlerW;
841 TRACE("%p %x %p\n",puiHandler,dwMessageFilter,pvContext);
842 gUIHandlerW = puiHandler;
843 gUIFilter = dwMessageFilter;
844 gUIContext = pvContext;
846 return prev;
849 /******************************************************************
850 * MsiLoadStringW [MSI.@]
852 * Loads a string from MSI's string resources.
854 * PARAMS
856 * handle [I] only -1 is handled currently
857 * id [I] id of the string to be loaded
858 * lpBuffer [O] buffer for the string to be written to
859 * nBufferMax [I] maximum size of the buffer in characters
860 * lang [I] the preferred language for the string
862 * RETURNS
864 * If successful, this function returns the language id of the string loaded
865 * If the function fails, the function returns zero.
867 * NOTES
869 * The type of the first parameter is unknown. LoadString's prototype
870 * suggests that it might be a module handle. I have made it an MSI handle
871 * for starters, as -1 is an invalid MSI handle, but not an invalid module
872 * handle. Maybe strings can be stored in an MSI database somehow.
874 LANGID WINAPI MsiLoadStringW( MSIHANDLE handle, UINT id, LPWSTR lpBuffer,
875 int nBufferMax, LANGID lang )
877 HRSRC hres;
878 HGLOBAL hResData;
879 LPWSTR p;
880 DWORD i, len;
882 TRACE("%ld %u %p %d %d\n", handle, id, lpBuffer, nBufferMax, lang);
884 if( handle != -1 )
885 FIXME("don't know how to deal with handle = %08lx\n", handle);
887 if( !lang )
888 lang = GetUserDefaultLangID();
890 hres = FindResourceExW( msi_hInstance, (LPCWSTR) RT_STRING,
891 (LPWSTR)1, lang );
892 if( !hres )
893 return 0;
894 hResData = LoadResource( msi_hInstance, hres );
895 if( !hResData )
896 return 0;
897 p = LockResource( hResData );
898 if( !p )
899 return 0;
901 for (i = 0; i < (id&0xf); i++)
902 p += *p + 1;
903 len = *p;
905 if( nBufferMax <= len )
906 return 0;
908 memcpy( lpBuffer, p+1, len * sizeof(WCHAR));
909 lpBuffer[ len ] = 0;
911 TRACE("found -> %s\n", debugstr_w(lpBuffer));
913 return lang;
916 LANGID WINAPI MsiLoadStringA( MSIHANDLE handle, UINT id, LPSTR lpBuffer,
917 int nBufferMax, LANGID lang )
919 LPWSTR bufW;
920 LANGID r;
921 DWORD len;
923 bufW = msi_alloc(nBufferMax*sizeof(WCHAR));
924 r = MsiLoadStringW(handle, id, bufW, nBufferMax, lang);
925 if( r )
927 len = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL );
928 if( len <= nBufferMax )
929 WideCharToMultiByte( CP_ACP, 0, bufW, -1,
930 lpBuffer, nBufferMax, NULL, NULL );
931 else
932 r = 0;
934 msi_free(bufW);
935 return r;
938 INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf,
939 DWORD *pcchBuf)
941 char szProduct[GUID_SIZE];
943 TRACE("%s %p %p\n", debugstr_a(szComponent), lpPathBuf, pcchBuf);
945 if (MsiGetProductCodeA( szComponent, szProduct ) != ERROR_SUCCESS)
946 return INSTALLSTATE_UNKNOWN;
948 return MsiGetComponentPathA( szProduct, szComponent, lpPathBuf, pcchBuf );
951 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPWSTR lpPathBuf,
952 DWORD *pcchBuf)
954 WCHAR szProduct[GUID_SIZE];
956 TRACE("%s %p %p\n", debugstr_w(szComponent), lpPathBuf, pcchBuf);
958 if (MsiGetProductCodeW( szComponent, szProduct ) != ERROR_SUCCESS)
959 return INSTALLSTATE_UNKNOWN;
961 return MsiGetComponentPathW( szProduct, szComponent, lpPathBuf, pcchBuf );
964 UINT WINAPI MsiMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType,
965 WORD wLanguageId, DWORD f)
967 FIXME("%p %s %s %u %08x %08x\n", hWnd, debugstr_a(lpText), debugstr_a(lpCaption),
968 uType, wLanguageId, f);
969 return MessageBoxExA(hWnd,lpText,lpCaption,uType,wLanguageId);
972 UINT WINAPI MsiMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType,
973 WORD wLanguageId, DWORD f)
975 FIXME("%p %s %s %u %08x %08x\n", hWnd, debugstr_w(lpText), debugstr_w(lpCaption),
976 uType, wLanguageId, f);
977 return MessageBoxExW(hWnd,lpText,lpCaption,uType,wLanguageId);
980 UINT WINAPI MsiProvideAssemblyA( LPCSTR szAssemblyName, LPCSTR szAppContext,
981 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf,
982 DWORD* pcchPathBuf )
984 FIXME("%s %s %08x %08x %p %p\n", debugstr_a(szAssemblyName),
985 debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
986 pcchPathBuf);
987 return ERROR_CALL_NOT_IMPLEMENTED;
990 UINT WINAPI MsiProvideAssemblyW( LPCWSTR szAssemblyName, LPCWSTR szAppContext,
991 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf,
992 DWORD* pcchPathBuf )
994 FIXME("%s %s %08x %08x %p %p\n", debugstr_w(szAssemblyName),
995 debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
996 pcchPathBuf);
997 return ERROR_CALL_NOT_IMPLEMENTED;
1000 UINT WINAPI MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor,
1001 LPSTR szPath, DWORD *pcchPath, DWORD *pcchArgs )
1003 FIXME("%s %p %p %p\n", debugstr_a(szDescriptor), szPath, pcchPath, pcchArgs );
1004 return ERROR_CALL_NOT_IMPLEMENTED;
1007 UINT WINAPI MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor,
1008 LPWSTR szPath, DWORD *pcchPath, DWORD *pcchArgs )
1010 FIXME("%s %p %p %p\n", debugstr_w(szDescriptor), szPath, pcchPath, pcchArgs );
1011 return ERROR_CALL_NOT_IMPLEMENTED;
1014 HRESULT WINAPI MsiGetFileSignatureInformationA( LPCSTR szSignedObjectPath,
1015 DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData,
1016 DWORD* pcbHashData)
1018 FIXME("%s %08x %p %p %p\n", debugstr_a(szSignedObjectPath), dwFlags,
1019 ppcCertContext, pbHashData, pcbHashData);
1020 return ERROR_CALL_NOT_IMPLEMENTED;
1023 HRESULT WINAPI MsiGetFileSignatureInformationW( LPCWSTR szSignedObjectPath,
1024 DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData,
1025 DWORD* pcbHashData)
1027 FIXME("%s %08x %p %p %p\n", debugstr_w(szSignedObjectPath), dwFlags,
1028 ppcCertContext, pbHashData, pcbHashData);
1029 return ERROR_CALL_NOT_IMPLEMENTED;
1032 UINT WINAPI MsiGetProductPropertyA( MSIHANDLE hProduct, LPCSTR szProperty,
1033 LPSTR szValue, DWORD *pccbValue )
1035 FIXME("%ld %s %p %p\n", hProduct, debugstr_a(szProperty), szValue, pccbValue);
1036 return ERROR_CALL_NOT_IMPLEMENTED;
1039 UINT WINAPI MsiGetProductPropertyW( MSIHANDLE hProduct, LPCWSTR szProperty,
1040 LPWSTR szValue, DWORD *pccbValue )
1042 FIXME("%ld %s %p %p\n", hProduct, debugstr_w(szProperty), szValue, pccbValue);
1043 return ERROR_CALL_NOT_IMPLEMENTED;
1046 UINT WINAPI MsiVerifyPackageA( LPCSTR szPackage )
1048 UINT r;
1049 LPWSTR szPack = NULL;
1051 TRACE("%s\n", debugstr_a(szPackage) );
1053 if( szPackage )
1055 szPack = strdupAtoW( szPackage );
1056 if( !szPack )
1057 return ERROR_OUTOFMEMORY;
1060 r = MsiVerifyPackageW( szPack );
1062 msi_free( szPack );
1064 return r;
1067 UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage )
1069 MSIHANDLE handle;
1070 UINT r;
1072 TRACE("%s\n", debugstr_w(szPackage) );
1074 r = MsiOpenDatabaseW( szPackage, MSIDBOPEN_READONLY, &handle );
1075 MsiCloseHandle( handle );
1077 return r;
1080 static INSTALLSTATE WINAPI MSI_GetComponentPath(LPCWSTR szProduct, LPCWSTR szComponent,
1081 awstring* lpPathBuf, DWORD* pcchBuf)
1083 WCHAR squished_pc[GUID_SIZE], squished_comp[GUID_SIZE];
1084 UINT rc;
1085 HKEY hkey = 0;
1086 LPWSTR path = NULL;
1087 INSTALLSTATE r;
1089 TRACE("%s %s %p %p\n", debugstr_w(szProduct),
1090 debugstr_w(szComponent), lpPathBuf->str.w, pcchBuf);
1092 if( !szProduct || !szComponent )
1093 return INSTALLSTATE_INVALIDARG;
1094 if( lpPathBuf->str.w && !pcchBuf )
1095 return INSTALLSTATE_INVALIDARG;
1097 if (!squash_guid( szProduct, squished_pc ) ||
1098 !squash_guid( szComponent, squished_comp ))
1099 return INSTALLSTATE_INVALIDARG;
1101 rc = MSIREG_OpenProductsKey( szProduct, &hkey, FALSE);
1102 if( rc != ERROR_SUCCESS )
1103 return INSTALLSTATE_UNKNOWN;
1105 RegCloseKey(hkey);
1107 rc = MSIREG_OpenComponentsKey( szComponent, &hkey, FALSE);
1108 if( rc != ERROR_SUCCESS )
1109 return INSTALLSTATE_UNKNOWN;
1111 path = msi_reg_get_val_str( hkey, squished_pc );
1112 RegCloseKey(hkey);
1114 TRACE("found path of (%s:%s)(%s)\n", debugstr_w(szComponent),
1115 debugstr_w(szProduct), debugstr_w(path));
1117 if (!path)
1118 return INSTALLSTATE_UNKNOWN;
1120 if (path[0])
1121 r = INSTALLSTATE_LOCAL;
1122 else
1123 r = INSTALLSTATE_NOTUSED;
1125 msi_strcpy_to_awstring( path, lpPathBuf, pcchBuf );
1127 msi_free( path );
1128 return r;
1131 /******************************************************************
1132 * MsiGetComponentPathW [MSI.@]
1134 INSTALLSTATE WINAPI MsiGetComponentPathW(LPCWSTR szProduct, LPCWSTR szComponent,
1135 LPWSTR lpPathBuf, DWORD* pcchBuf)
1137 awstring path;
1139 path.unicode = TRUE;
1140 path.str.w = lpPathBuf;
1142 return MSI_GetComponentPath( szProduct, szComponent, &path, pcchBuf );
1145 /******************************************************************
1146 * MsiGetComponentPathA [MSI.@]
1148 INSTALLSTATE WINAPI MsiGetComponentPathA(LPCSTR szProduct, LPCSTR szComponent,
1149 LPSTR lpPathBuf, DWORD* pcchBuf)
1151 LPWSTR szwProduct, szwComponent = NULL;
1152 INSTALLSTATE r = INSTALLSTATE_UNKNOWN;
1153 awstring path;
1155 szwProduct = strdupAtoW( szProduct );
1156 if( szProduct && !szwProduct)
1157 goto end;
1159 szwComponent = strdupAtoW( szComponent );
1160 if( szComponent && !szwComponent )
1161 goto end;
1163 path.unicode = FALSE;
1164 path.str.a = lpPathBuf;
1166 r = MSI_GetComponentPath( szwProduct, szwComponent, &path, pcchBuf );
1168 end:
1169 msi_free( szwProduct );
1170 msi_free( szwComponent );
1172 return r;
1175 /******************************************************************
1176 * MsiQueryFeatureStateA [MSI.@]
1178 INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature)
1180 LPWSTR szwProduct = NULL, szwFeature= NULL;
1181 INSTALLSTATE rc = INSTALLSTATE_UNKNOWN;
1183 szwProduct = strdupAtoW( szProduct );
1184 if ( szProduct && !szwProduct )
1185 goto end;
1187 szwFeature = strdupAtoW( szFeature );
1188 if ( szFeature && !szwFeature )
1189 goto end;
1191 rc = MsiQueryFeatureStateW(szwProduct, szwFeature);
1193 end:
1194 msi_free( szwProduct);
1195 msi_free( szwFeature);
1197 return rc;
1200 /******************************************************************
1201 * MsiQueryFeatureStateW [MSI.@]
1203 * Checks the state of a feature
1205 * PARAMS
1206 * szProduct [I] Product's GUID string
1207 * szFeature [I] Feature's GUID string
1209 * RETURNS
1210 * INSTALLSTATE_LOCAL Feature is installed and useable
1211 * INSTALLSTATE_ABSENT Feature is absent
1212 * INSTALLSTATE_ADVERTISED Feature should be installed on demand
1213 * INSTALLSTATE_UNKNOWN An error occurred
1214 * INSTALLSTATE_INVALIDARG One of the GUIDs was invalid
1217 INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature)
1219 WCHAR squishProduct[33], comp[GUID_SIZE];
1220 GUID guid;
1221 LPWSTR components, p, parent_feature;
1222 UINT rc;
1223 HKEY hkey;
1224 INSTALLSTATE r;
1225 BOOL missing = FALSE;
1227 TRACE("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature));
1229 if (!szProduct || !szFeature)
1230 return INSTALLSTATE_INVALIDARG;
1232 if (!squash_guid( szProduct, squishProduct ))
1233 return INSTALLSTATE_INVALIDARG;
1235 /* check that it's installed at all */
1236 rc = MSIREG_OpenUserFeaturesKey(szProduct, &hkey, FALSE);
1237 if (rc != ERROR_SUCCESS)
1238 return INSTALLSTATE_UNKNOWN;
1240 parent_feature = msi_reg_get_val_str( hkey, szFeature );
1241 RegCloseKey(hkey);
1243 if (!parent_feature)
1244 return INSTALLSTATE_UNKNOWN;
1246 r = (parent_feature[0] == 6) ? INSTALLSTATE_ABSENT : INSTALLSTATE_LOCAL;
1247 msi_free(parent_feature);
1248 if (r == INSTALLSTATE_ABSENT)
1249 return r;
1251 /* now check if it's complete or advertised */
1252 rc = MSIREG_OpenFeaturesKey(szProduct, &hkey, FALSE);
1253 if (rc != ERROR_SUCCESS)
1254 return INSTALLSTATE_UNKNOWN;
1256 components = msi_reg_get_val_str( hkey, szFeature );
1257 RegCloseKey(hkey);
1259 TRACE("rc = %d buffer = %s\n", rc, debugstr_w(components));
1261 if (!components)
1263 ERR("components missing %s %s\n",
1264 debugstr_w(szProduct), debugstr_w(szFeature));
1265 return INSTALLSTATE_UNKNOWN;
1268 for( p = components; *p != 2 ; p += 20)
1270 if (!decode_base85_guid( p, &guid ))
1272 ERR("%s\n", debugstr_w(p));
1273 break;
1275 StringFromGUID2(&guid, comp, GUID_SIZE);
1276 r = MsiGetComponentPathW(szProduct, comp, NULL, 0);
1277 TRACE("component %s state %d\n", debugstr_guid(&guid), r);
1278 switch (r)
1280 case INSTALLSTATE_NOTUSED:
1281 case INSTALLSTATE_LOCAL:
1282 case INSTALLSTATE_SOURCE:
1283 break;
1284 default:
1285 missing = TRUE;
1289 TRACE("%s %s -> %d\n", debugstr_w(szProduct), debugstr_w(szFeature), r);
1290 msi_free(components);
1292 if (missing)
1293 return INSTALLSTATE_ADVERTISED;
1295 return INSTALLSTATE_LOCAL;
1298 /******************************************************************
1299 * MsiGetFileVersionA [MSI.@]
1301 UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf,
1302 DWORD* pcchVersionBuf, LPSTR lpLangBuf, DWORD* pcchLangBuf)
1304 LPWSTR szwFilePath = NULL, lpwVersionBuff = NULL, lpwLangBuff = NULL;
1305 UINT ret = ERROR_OUTOFMEMORY;
1307 if( szFilePath )
1309 szwFilePath = strdupAtoW( szFilePath );
1310 if( !szwFilePath )
1311 goto end;
1314 if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf )
1316 lpwVersionBuff = msi_alloc(*pcchVersionBuf*sizeof(WCHAR));
1317 if( !lpwVersionBuff )
1318 goto end;
1321 if( lpLangBuf && pcchLangBuf && *pcchLangBuf )
1323 lpwLangBuff = msi_alloc(*pcchLangBuf*sizeof(WCHAR));
1324 if( !lpwLangBuff )
1325 goto end;
1328 ret = MsiGetFileVersionW(szwFilePath, lpwVersionBuff, pcchVersionBuf,
1329 lpwLangBuff, pcchLangBuf);
1331 if( lpwVersionBuff )
1332 WideCharToMultiByte(CP_ACP, 0, lpwVersionBuff, -1,
1333 lpVersionBuf, *pcchVersionBuf, NULL, NULL);
1334 if( lpwLangBuff )
1335 WideCharToMultiByte(CP_ACP, 0, lpwLangBuff, -1,
1336 lpLangBuf, *pcchLangBuf, NULL, NULL);
1338 end:
1339 msi_free(szwFilePath);
1340 msi_free(lpwVersionBuff);
1341 msi_free(lpwLangBuff);
1343 return ret;
1346 /******************************************************************
1347 * MsiGetFileVersionW [MSI.@]
1349 UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf,
1350 DWORD* pcchVersionBuf, LPWSTR lpLangBuf, DWORD* pcchLangBuf)
1352 static const WCHAR szVersionResource[] = {'\\',0};
1353 static const WCHAR szVersionFormat[] = {
1354 '%','d','.','%','d','.','%','d','.','%','d',0};
1355 static const WCHAR szLangFormat[] = {'%','d',0};
1356 UINT ret = 0;
1357 DWORD dwVerLen;
1358 LPVOID lpVer = NULL;
1359 VS_FIXEDFILEINFO *ffi;
1360 UINT puLen;
1361 WCHAR tmp[32];
1363 TRACE("%s %p %d %p %d\n", debugstr_w(szFilePath),
1364 lpVersionBuf, pcchVersionBuf?*pcchVersionBuf:0,
1365 lpLangBuf, pcchLangBuf?*pcchLangBuf:0);
1367 dwVerLen = GetFileVersionInfoSizeW(szFilePath, NULL);
1368 if( !dwVerLen )
1369 return GetLastError();
1371 lpVer = msi_alloc(dwVerLen);
1372 if( !lpVer )
1374 ret = ERROR_OUTOFMEMORY;
1375 goto end;
1378 if( !GetFileVersionInfoW(szFilePath, 0, dwVerLen, lpVer) )
1380 ret = GetLastError();
1381 goto end;
1383 if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf )
1385 if( VerQueryValueW(lpVer, szVersionResource, (LPVOID*)&ffi, &puLen) &&
1386 (puLen > 0) )
1388 wsprintfW(tmp, szVersionFormat,
1389 HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS),
1390 HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS));
1391 lstrcpynW(lpVersionBuf, tmp, *pcchVersionBuf);
1392 *pcchVersionBuf = lstrlenW(lpVersionBuf);
1394 else
1396 *lpVersionBuf = 0;
1397 *pcchVersionBuf = 0;
1401 if( lpLangBuf && pcchLangBuf && *pcchLangBuf )
1403 DWORD lang = GetUserDefaultLangID();
1405 FIXME("Retrieve language from file\n");
1406 wsprintfW(tmp, szLangFormat, lang);
1407 lstrcpynW(lpLangBuf, tmp, *pcchLangBuf);
1408 *pcchLangBuf = lstrlenW(lpLangBuf);
1411 end:
1412 msi_free(lpVer);
1413 return ret;
1416 /***********************************************************************
1417 * MsiGetFeatureUsageW [MSI.@]
1419 UINT WINAPI MsiGetFeatureUsageW( LPCWSTR szProduct, LPCWSTR szFeature,
1420 DWORD* pdwUseCount, WORD* pwDateUsed )
1422 FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szFeature),
1423 pdwUseCount, pwDateUsed);
1424 return ERROR_CALL_NOT_IMPLEMENTED;
1427 /***********************************************************************
1428 * MsiGetFeatureUsageA [MSI.@]
1430 UINT WINAPI MsiGetFeatureUsageA( LPCSTR szProduct, LPCSTR szFeature,
1431 DWORD* pdwUseCount, WORD* pwDateUsed )
1433 LPWSTR prod = NULL, feat = NULL;
1434 UINT ret = ERROR_OUTOFMEMORY;
1436 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szFeature),
1437 pdwUseCount, pwDateUsed);
1439 prod = strdupAtoW( szProduct );
1440 if (szProduct && !prod)
1441 goto end;
1443 feat = strdupAtoW( szFeature );
1444 if (szFeature && !feat)
1445 goto end;
1447 ret = MsiGetFeatureUsageW( prod, feat, pdwUseCount, pwDateUsed );
1449 end:
1450 msi_free( prod );
1451 msi_free( feat );
1453 return ret;
1456 /***********************************************************************
1457 * MsiUseFeatureExW [MSI.@]
1459 INSTALLSTATE WINAPI MsiUseFeatureExW( LPCWSTR szProduct, LPCWSTR szFeature,
1460 DWORD dwInstallMode, DWORD dwReserved )
1462 INSTALLSTATE state;
1464 TRACE("%s %s %i %i\n", debugstr_w(szProduct), debugstr_w(szFeature),
1465 dwInstallMode, dwReserved);
1467 state = MsiQueryFeatureStateW( szProduct, szFeature );
1469 if (dwReserved)
1470 return INSTALLSTATE_INVALIDARG;
1472 if (state == INSTALLSTATE_LOCAL && dwInstallMode != INSTALLMODE_NODETECTION)
1474 FIXME("mark product %s feature %s as used\n",
1475 debugstr_w(szProduct), debugstr_w(szFeature) );
1478 return state;
1481 /***********************************************************************
1482 * MsiUseFeatureExA [MSI.@]
1484 INSTALLSTATE WINAPI MsiUseFeatureExA( LPCSTR szProduct, LPCSTR szFeature,
1485 DWORD dwInstallMode, DWORD dwReserved )
1487 INSTALLSTATE ret = INSTALLSTATE_UNKNOWN;
1488 LPWSTR prod = NULL, feat = NULL;
1490 TRACE("%s %s %i %i\n", debugstr_a(szProduct), debugstr_a(szFeature),
1491 dwInstallMode, dwReserved);
1493 prod = strdupAtoW( szProduct );
1494 if (szProduct && !prod)
1495 goto end;
1497 feat = strdupAtoW( szFeature );
1498 if (szFeature && !feat)
1499 goto end;
1501 ret = MsiUseFeatureExW( prod, feat, dwInstallMode, dwReserved );
1503 end:
1504 msi_free( prod );
1505 msi_free( feat );
1507 return ret;
1510 /***********************************************************************
1511 * MsiUseFeatureW [MSI.@]
1513 INSTALLSTATE WINAPI MsiUseFeatureW( LPCWSTR szProduct, LPCWSTR szFeature )
1515 return MsiUseFeatureExW(szProduct, szFeature, 0, 0);
1518 /***********************************************************************
1519 * MsiUseFeatureA [MSI.@]
1521 INSTALLSTATE WINAPI MsiUseFeatureA( LPCSTR szProduct, LPCSTR szFeature )
1523 return MsiUseFeatureExA(szProduct, szFeature, 0, 0);
1526 /***********************************************************************
1527 * MSI_ProvideQualifiedComponentEx [internal]
1529 static UINT WINAPI MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent,
1530 LPCWSTR szQualifier, DWORD dwInstallMode, LPCWSTR szProduct,
1531 DWORD Unused1, DWORD Unused2, awstring *lpPathBuf,
1532 DWORD* pcchPathBuf)
1534 WCHAR product[MAX_FEATURE_CHARS+1], component[MAX_FEATURE_CHARS+1],
1535 feature[MAX_FEATURE_CHARS+1];
1536 LPWSTR info;
1537 HKEY hkey;
1538 DWORD sz;
1539 UINT rc;
1541 TRACE("%s %s %i %s %i %i %p %p\n", debugstr_w(szComponent),
1542 debugstr_w(szQualifier), dwInstallMode, debugstr_w(szProduct),
1543 Unused1, Unused2, lpPathBuf, pcchPathBuf);
1545 rc = MSIREG_OpenUserComponentsKey(szComponent, &hkey, FALSE);
1546 if (rc != ERROR_SUCCESS)
1547 return ERROR_INDEX_ABSENT;
1549 info = msi_reg_get_val_str( hkey, szQualifier );
1550 RegCloseKey(hkey);
1552 if (!info)
1553 return ERROR_INDEX_ABSENT;
1555 MsiDecomposeDescriptorW(info, product, feature, component, &sz);
1557 if (!szProduct)
1558 rc = MSI_GetComponentPath(product, component, lpPathBuf, pcchPathBuf);
1559 else
1560 rc = MSI_GetComponentPath(szProduct, component, lpPathBuf, pcchPathBuf);
1562 msi_free( info );
1564 if (rc != INSTALLSTATE_LOCAL)
1565 return ERROR_FILE_NOT_FOUND;
1567 return ERROR_SUCCESS;
1570 /***********************************************************************
1571 * MsiProvideQualifiedComponentExW [MSI.@]
1573 UINT WINAPI MsiProvideQualifiedComponentExW(LPCWSTR szComponent,
1574 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR szProduct,
1575 DWORD Unused1, DWORD Unused2, LPWSTR lpPathBuf,
1576 DWORD* pcchPathBuf)
1578 awstring path;
1580 path.unicode = TRUE;
1581 path.str.w = lpPathBuf;
1583 return MSI_ProvideQualifiedComponentEx(szComponent, szQualifier,
1584 dwInstallMode, szProduct, Unused1, Unused2, &path, pcchPathBuf);
1587 /***********************************************************************
1588 * MsiProvideQualifiedComponentExA [MSI.@]
1590 UINT WINAPI MsiProvideQualifiedComponentExA(LPCSTR szComponent,
1591 LPCSTR szQualifier, DWORD dwInstallMode, LPSTR szProduct,
1592 DWORD Unused1, DWORD Unused2, LPSTR lpPathBuf,
1593 DWORD* pcchPathBuf)
1595 LPWSTR szwComponent, szwQualifier = NULL, szwProduct = NULL;
1596 UINT r = ERROR_OUTOFMEMORY;
1597 awstring path;
1599 TRACE("%s %s %u %s %u %u %p %p\n", debugstr_a(szComponent),
1600 debugstr_a(szQualifier), dwInstallMode, debugstr_a(szProduct),
1601 Unused1, Unused2, lpPathBuf, pcchPathBuf);
1603 szwComponent = strdupAtoW( szComponent );
1604 if (szComponent && !szwComponent)
1605 goto end;
1607 szwQualifier = strdupAtoW( szQualifier );
1608 if (szQualifier && !szwQualifier)
1609 goto end;
1611 szwProduct = strdupAtoW( szProduct );
1612 if (szProduct && !szwProduct)
1613 goto end;
1615 path.unicode = FALSE;
1616 path.str.a = lpPathBuf;
1618 r = MSI_ProvideQualifiedComponentEx(szwComponent, szwQualifier,
1619 dwInstallMode, szwProduct, Unused1,
1620 Unused2, &path, pcchPathBuf);
1621 end:
1622 msi_free(szwProduct);
1623 msi_free(szwComponent);
1624 msi_free(szwQualifier);
1626 return r;
1629 /***********************************************************************
1630 * MsiProvideQualifiedComponentW [MSI.@]
1632 UINT WINAPI MsiProvideQualifiedComponentW( LPCWSTR szComponent,
1633 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR lpPathBuf,
1634 DWORD* pcchPathBuf)
1636 return MsiProvideQualifiedComponentExW(szComponent, szQualifier,
1637 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
1640 /***********************************************************************
1641 * MsiProvideQualifiedComponentA [MSI.@]
1643 UINT WINAPI MsiProvideQualifiedComponentA( LPCSTR szComponent,
1644 LPCSTR szQualifier, DWORD dwInstallMode, LPSTR lpPathBuf,
1645 DWORD* pcchPathBuf)
1647 return MsiProvideQualifiedComponentExA(szComponent, szQualifier,
1648 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
1651 /***********************************************************************
1652 * MSI_GetUserInfo [internal]
1654 static USERINFOSTATE WINAPI MSI_GetUserInfo(LPCWSTR szProduct,
1655 awstring *lpUserNameBuf, DWORD* pcchUserNameBuf,
1656 awstring *lpOrgNameBuf, DWORD* pcchOrgNameBuf,
1657 awstring *lpSerialBuf, DWORD* pcchSerialBuf)
1659 HKEY hkey;
1660 LPWSTR user, org, serial;
1661 UINT r;
1662 USERINFOSTATE state;
1664 TRACE("%s %p %p %p %p %p %p\n",debugstr_w(szProduct), lpUserNameBuf,
1665 pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf,
1666 pcchSerialBuf);
1668 if (!szProduct)
1669 return USERINFOSTATE_INVALIDARG;
1671 r = MSIREG_OpenUninstallKey(szProduct, &hkey, FALSE);
1672 if (r != ERROR_SUCCESS)
1673 return USERINFOSTATE_UNKNOWN;
1675 user = msi_reg_get_val_str( hkey, INSTALLPROPERTY_REGOWNERW );
1676 org = msi_reg_get_val_str( hkey, INSTALLPROPERTY_REGCOMPANYW );
1677 serial = msi_reg_get_val_str( hkey, INSTALLPROPERTY_PRODUCTIDW );
1679 RegCloseKey(hkey);
1681 state = USERINFOSTATE_PRESENT;
1683 if (user)
1685 r = msi_strcpy_to_awstring( user, lpUserNameBuf, pcchUserNameBuf );
1686 if (r == ERROR_MORE_DATA)
1687 state = USERINFOSTATE_MOREDATA;
1689 else
1690 state = USERINFOSTATE_ABSENT;
1691 if (org)
1693 r = msi_strcpy_to_awstring( org, lpOrgNameBuf, pcchOrgNameBuf );
1694 if (r == ERROR_MORE_DATA && state == USERINFOSTATE_PRESENT)
1695 state = USERINFOSTATE_MOREDATA;
1697 /* msdn states: The user information is considered to be present even in the absence of a company name. */
1698 if (serial)
1700 r = msi_strcpy_to_awstring( serial, lpSerialBuf, pcchSerialBuf );
1701 if (r == ERROR_MORE_DATA && state == USERINFOSTATE_PRESENT)
1702 state = USERINFOSTATE_MOREDATA;
1704 else
1705 state = USERINFOSTATE_ABSENT;
1707 msi_free( user );
1708 msi_free( org );
1709 msi_free( serial );
1711 return state;
1714 /***********************************************************************
1715 * MsiGetUserInfoW [MSI.@]
1717 USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct,
1718 LPWSTR lpUserNameBuf, DWORD* pcchUserNameBuf,
1719 LPWSTR lpOrgNameBuf, DWORD* pcchOrgNameBuf,
1720 LPWSTR lpSerialBuf, DWORD* pcchSerialBuf)
1722 awstring user, org, serial;
1724 user.unicode = TRUE;
1725 user.str.w = lpUserNameBuf;
1726 org.unicode = TRUE;
1727 org.str.w = lpOrgNameBuf;
1728 serial.unicode = TRUE;
1729 serial.str.w = lpSerialBuf;
1731 return MSI_GetUserInfo( szProduct, &user, pcchUserNameBuf,
1732 &org, pcchOrgNameBuf,
1733 &serial, pcchSerialBuf );
1736 USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR szProduct,
1737 LPSTR lpUserNameBuf, DWORD* pcchUserNameBuf,
1738 LPSTR lpOrgNameBuf, DWORD* pcchOrgNameBuf,
1739 LPSTR lpSerialBuf, DWORD* pcchSerialBuf)
1741 awstring user, org, serial;
1742 LPWSTR prod;
1743 UINT r;
1745 prod = strdupAtoW( szProduct );
1746 if (szProduct && !prod)
1747 return ERROR_OUTOFMEMORY;
1749 user.unicode = FALSE;
1750 user.str.a = lpUserNameBuf;
1751 org.unicode = FALSE;
1752 org.str.a = lpOrgNameBuf;
1753 serial.unicode = FALSE;
1754 serial.str.a = lpSerialBuf;
1756 r = MSI_GetUserInfo( prod, &user, pcchUserNameBuf,
1757 &org, pcchOrgNameBuf,
1758 &serial, pcchSerialBuf );
1760 msi_free( prod );
1762 return r;
1765 UINT WINAPI MsiCollectUserInfoW(LPCWSTR szProduct)
1767 MSIHANDLE handle;
1768 UINT rc;
1769 MSIPACKAGE *package;
1770 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
1772 TRACE("(%s)\n",debugstr_w(szProduct));
1774 rc = MsiOpenProductW(szProduct,&handle);
1775 if (rc != ERROR_SUCCESS)
1776 return ERROR_INVALID_PARAMETER;
1778 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
1779 rc = ACTION_PerformUIAction(package, szFirstRun, -1);
1780 msiobj_release( &package->hdr );
1782 MsiCloseHandle(handle);
1784 return rc;
1787 UINT WINAPI MsiCollectUserInfoA(LPCSTR szProduct)
1789 MSIHANDLE handle;
1790 UINT rc;
1791 MSIPACKAGE *package;
1792 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
1794 TRACE("(%s)\n",debugstr_a(szProduct));
1796 rc = MsiOpenProductA(szProduct,&handle);
1797 if (rc != ERROR_SUCCESS)
1798 return ERROR_INVALID_PARAMETER;
1800 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
1801 rc = ACTION_PerformUIAction(package, szFirstRun, -1);
1802 msiobj_release( &package->hdr );
1804 MsiCloseHandle(handle);
1806 return rc;
1809 /***********************************************************************
1810 * MsiConfigureFeatureA [MSI.@]
1812 UINT WINAPI MsiConfigureFeatureA(LPCSTR szProduct, LPCSTR szFeature, INSTALLSTATE eInstallState)
1814 LPWSTR prod, feat = NULL;
1815 UINT r = ERROR_OUTOFMEMORY;
1817 TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature), eInstallState);
1819 prod = strdupAtoW( szProduct );
1820 if (szProduct && !prod)
1821 goto end;
1823 feat = strdupAtoW( szFeature );
1824 if (szFeature && !feat)
1825 goto end;
1827 r = MsiConfigureFeatureW(prod, feat, eInstallState);
1829 end:
1830 msi_free(feat);
1831 msi_free(prod);
1833 return r;
1836 /***********************************************************************
1837 * MsiConfigureFeatureW [MSI.@]
1839 UINT WINAPI MsiConfigureFeatureW(LPCWSTR szProduct, LPCWSTR szFeature, INSTALLSTATE eInstallState)
1841 static const WCHAR szCostInit[] = { 'C','o','s','t','I','n','i','t','i','a','l','i','z','e',0 };
1842 MSIPACKAGE *package = NULL;
1843 UINT r;
1844 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH];
1845 DWORD sz;
1847 TRACE("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature), eInstallState);
1849 if (!szProduct || !szFeature)
1850 return ERROR_INVALID_PARAMETER;
1852 switch (eInstallState)
1854 case INSTALLSTATE_DEFAULT:
1855 /* FIXME: how do we figure out the default location? */
1856 eInstallState = INSTALLSTATE_LOCAL;
1857 break;
1858 case INSTALLSTATE_LOCAL:
1859 case INSTALLSTATE_SOURCE:
1860 case INSTALLSTATE_ABSENT:
1861 case INSTALLSTATE_ADVERTISED:
1862 break;
1863 default:
1864 return ERROR_INVALID_PARAMETER;
1867 r = MSI_OpenProductW( szProduct, &package );
1868 if (r != ERROR_SUCCESS)
1869 return r;
1871 sz = sizeof(sourcepath);
1872 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
1873 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
1875 sz = sizeof(filename);
1876 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
1877 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
1879 lstrcatW( sourcepath, filename );
1881 MsiSetInternalUI( INSTALLUILEVEL_BASIC, NULL );
1883 r = ACTION_PerformUIAction( package, szCostInit, -1 );
1884 if (r != ERROR_SUCCESS)
1885 goto end;
1887 r = MSI_SetFeatureStateW( package, szFeature, eInstallState);
1888 if (r != ERROR_SUCCESS)
1889 goto end;
1891 r = MSI_InstallPackage( package, sourcepath, NULL );
1893 end:
1894 msiobj_release( &package->hdr );
1896 return r;
1899 /***********************************************************************
1900 * MsiCreateAndVerifyInstallerDirectory [MSI.@]
1902 * Notes: undocumented
1904 UINT WINAPI MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved)
1906 WCHAR path[MAX_PATH];
1908 TRACE("%d\n", dwReserved);
1910 if (dwReserved)
1912 FIXME("dwReserved=%d\n", dwReserved);
1913 return ERROR_INVALID_PARAMETER;
1916 if (!GetWindowsDirectoryW(path, MAX_PATH))
1917 return ERROR_FUNCTION_FAILED;
1919 lstrcatW(path, installerW);
1921 if (!CreateDirectoryW(path, NULL))
1922 return ERROR_FUNCTION_FAILED;
1924 return ERROR_SUCCESS;
1927 /***********************************************************************
1928 * MsiGetShortcutTargetA [MSI.@]
1930 UINT WINAPI MsiGetShortcutTargetA( LPCSTR szShortcutTarget,
1931 LPSTR szProductCode, LPSTR szFeatureId,
1932 LPSTR szComponentCode )
1934 LPWSTR target;
1935 const int len = MAX_FEATURE_CHARS+1;
1936 WCHAR product[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1], component[MAX_FEATURE_CHARS+1];
1937 UINT r;
1939 target = strdupAtoW( szShortcutTarget );
1940 if (szShortcutTarget && !target )
1941 return ERROR_OUTOFMEMORY;
1942 product[0] = 0;
1943 feature[0] = 0;
1944 component[0] = 0;
1945 r = MsiGetShortcutTargetW( target, product, feature, component );
1946 msi_free( target );
1947 if (r == ERROR_SUCCESS)
1949 WideCharToMultiByte( CP_ACP, 0, product, -1, szProductCode, len, NULL, NULL );
1950 WideCharToMultiByte( CP_ACP, 0, feature, -1, szFeatureId, len, NULL, NULL );
1951 WideCharToMultiByte( CP_ACP, 0, component, -1, szComponentCode, len, NULL, NULL );
1953 return r;
1956 /***********************************************************************
1957 * MsiGetShortcutTargetW [MSI.@]
1959 UINT WINAPI MsiGetShortcutTargetW( LPCWSTR szShortcutTarget,
1960 LPWSTR szProductCode, LPWSTR szFeatureId,
1961 LPWSTR szComponentCode )
1963 IShellLinkDataList *dl = NULL;
1964 IPersistFile *pf = NULL;
1965 LPEXP_DARWIN_LINK darwin = NULL;
1966 HRESULT r, init;
1968 TRACE("%s %p %p %p\n", debugstr_w(szShortcutTarget),
1969 szProductCode, szFeatureId, szComponentCode );
1971 init = CoInitialize(NULL);
1973 r = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
1974 &IID_IPersistFile, (LPVOID*) &pf );
1975 if( SUCCEEDED( r ) )
1977 r = IPersistFile_Load( pf, szShortcutTarget,
1978 STGM_READ | STGM_SHARE_DENY_WRITE );
1979 if( SUCCEEDED( r ) )
1981 r = IPersistFile_QueryInterface( pf, &IID_IShellLinkDataList,
1982 (LPVOID*) &dl );
1983 if( SUCCEEDED( r ) )
1985 IShellLinkDataList_CopyDataBlock( dl, EXP_DARWIN_ID_SIG,
1986 (LPVOID) &darwin );
1987 IShellLinkDataList_Release( dl );
1990 IPersistFile_Release( pf );
1993 if (SUCCEEDED(init))
1994 CoUninitialize();
1996 TRACE("darwin = %p\n", darwin);
1998 if (darwin)
2000 DWORD sz;
2001 UINT ret;
2003 ret = MsiDecomposeDescriptorW( darwin->szwDarwinID,
2004 szProductCode, szFeatureId, szComponentCode, &sz );
2005 LocalFree( darwin );
2006 return ret;
2009 return ERROR_FUNCTION_FAILED;
2012 UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature,
2013 DWORD dwReinstallMode )
2015 MSIPACKAGE* package = NULL;
2016 UINT r;
2017 WCHAR sourcepath[MAX_PATH];
2018 WCHAR filename[MAX_PATH];
2019 static const WCHAR szLogVerbose[] = {
2020 ' ','L','O','G','V','E','R','B','O','S','E',0 };
2021 static const WCHAR szInstalled[] = { 'I','n','s','t','a','l','l','e','d',0};
2022 static const WCHAR szReinstall[] = {'R','E','I','N','S','T','A','L','L',0};
2023 static const WCHAR szReinstallMode[] = {'R','E','I','N','S','T','A','L','L','M','O','D','E',0};
2024 static const WCHAR szOne[] = {'1',0};
2025 WCHAR reinstallmode[11];
2026 LPWSTR ptr;
2027 DWORD sz;
2029 FIXME("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature),
2030 dwReinstallMode);
2032 ptr = reinstallmode;
2034 if (dwReinstallMode & REINSTALLMODE_FILEMISSING)
2035 *ptr++ = 'p';
2036 if (dwReinstallMode & REINSTALLMODE_FILEOLDERVERSION)
2037 *ptr++ = 'o';
2038 if (dwReinstallMode & REINSTALLMODE_FILEEQUALVERSION)
2039 *ptr++ = 'w';
2040 if (dwReinstallMode & REINSTALLMODE_FILEEXACT)
2041 *ptr++ = 'd';
2042 if (dwReinstallMode & REINSTALLMODE_FILEVERIFY)
2043 *ptr++ = 'c';
2044 if (dwReinstallMode & REINSTALLMODE_FILEREPLACE)
2045 *ptr++ = 'a';
2046 if (dwReinstallMode & REINSTALLMODE_USERDATA)
2047 *ptr++ = 'u';
2048 if (dwReinstallMode & REINSTALLMODE_MACHINEDATA)
2049 *ptr++ = 'm';
2050 if (dwReinstallMode & REINSTALLMODE_SHORTCUT)
2051 *ptr++ = 's';
2052 if (dwReinstallMode & REINSTALLMODE_PACKAGE)
2053 *ptr++ = 'v';
2054 *ptr = 0;
2056 sz = sizeof(sourcepath);
2057 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
2058 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
2060 sz = sizeof(filename);
2061 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
2062 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
2064 lstrcatW( sourcepath, filename );
2066 if (dwReinstallMode & REINSTALLMODE_PACKAGE)
2067 r = MSI_OpenPackageW( sourcepath, &package );
2068 else
2069 r = MSI_OpenProductW( szProduct, &package );
2071 if (r != ERROR_SUCCESS)
2072 return r;
2074 MSI_SetPropertyW( package, szReinstallMode, reinstallmode );
2075 MSI_SetPropertyW( package, szInstalled, szOne );
2076 MSI_SetPropertyW( package, szLogVerbose, szOne );
2077 MSI_SetPropertyW( package, szReinstall, szFeature );
2079 r = MSI_InstallPackage( package, sourcepath, NULL );
2081 msiobj_release( &package->hdr );
2083 return r;
2086 UINT WINAPI MsiReinstallFeatureA( LPCSTR szProduct, LPCSTR szFeature,
2087 DWORD dwReinstallMode )
2089 LPWSTR wszProduct;
2090 LPWSTR wszFeature;
2091 UINT rc;
2093 TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature),
2094 dwReinstallMode);
2096 wszProduct = strdupAtoW(szProduct);
2097 wszFeature = strdupAtoW(szFeature);
2099 rc = MsiReinstallFeatureW(wszProduct, wszFeature, dwReinstallMode);
2101 msi_free(wszProduct);
2102 msi_free(wszFeature);
2103 return rc;
2106 typedef struct
2108 unsigned int i[2];
2109 unsigned int buf[4];
2110 unsigned char in[64];
2111 unsigned char digest[16];
2112 } MD5_CTX;
2114 extern VOID WINAPI MD5Init( MD5_CTX *);
2115 extern VOID WINAPI MD5Update( MD5_CTX *, const unsigned char *, unsigned int );
2116 extern VOID WINAPI MD5Final( MD5_CTX *);
2118 /***********************************************************************
2119 * MsiGetFileHashW [MSI.@]
2121 UINT WINAPI MsiGetFileHashW( LPCWSTR szFilePath, DWORD dwOptions,
2122 PMSIFILEHASHINFO pHash )
2124 HANDLE handle, mapping;
2125 void *p;
2126 DWORD length;
2127 UINT r = ERROR_FUNCTION_FAILED;
2129 TRACE("%s %08x %p\n", debugstr_w(szFilePath), dwOptions, pHash );
2131 if (dwOptions)
2132 return ERROR_INVALID_PARAMETER;
2133 if (!pHash)
2134 return ERROR_INVALID_PARAMETER;
2135 if (pHash->dwFileHashInfoSize < sizeof *pHash)
2136 return ERROR_INVALID_PARAMETER;
2138 handle = CreateFileW( szFilePath, GENERIC_READ,
2139 FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL );
2140 if (handle == INVALID_HANDLE_VALUE)
2141 return ERROR_FILE_NOT_FOUND;
2143 length = GetFileSize( handle, NULL );
2145 mapping = CreateFileMappingW( handle, NULL, PAGE_READONLY, 0, 0, NULL );
2146 if (mapping)
2148 p = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, length );
2149 if (p)
2151 MD5_CTX ctx;
2153 MD5Init( &ctx );
2154 MD5Update( &ctx, p, length );
2155 MD5Final( &ctx );
2156 UnmapViewOfFile( p );
2158 memcpy( pHash->dwData, &ctx.digest, sizeof pHash->dwData );
2159 r = ERROR_SUCCESS;
2161 CloseHandle( mapping );
2163 CloseHandle( handle );
2165 return r;
2168 /***********************************************************************
2169 * MsiGetFileHashA [MSI.@]
2171 UINT WINAPI MsiGetFileHashA( LPCSTR szFilePath, DWORD dwOptions,
2172 PMSIFILEHASHINFO pHash )
2174 LPWSTR file;
2175 UINT r;
2177 TRACE("%s %08x %p\n", debugstr_a(szFilePath), dwOptions, pHash );
2179 file = strdupAtoW( szFilePath );
2180 if (szFilePath && !file)
2181 return ERROR_OUTOFMEMORY;
2183 r = MsiGetFileHashW( file, dwOptions, pHash );
2184 msi_free( file );
2185 return r;
2188 /***********************************************************************
2189 * MsiAdvertiseScriptW [MSI.@]
2191 UINT WINAPI MsiAdvertiseScriptW( LPCWSTR szScriptFile, DWORD dwFlags,
2192 PHKEY phRegData, BOOL fRemoveItems )
2194 FIXME("%s %08x %p %d\n",
2195 debugstr_w( szScriptFile ), dwFlags, phRegData, fRemoveItems );
2196 return ERROR_CALL_NOT_IMPLEMENTED;
2199 /***********************************************************************
2200 * MsiAdvertiseScriptA [MSI.@]
2202 UINT WINAPI MsiAdvertiseScriptA( LPCSTR szScriptFile, DWORD dwFlags,
2203 PHKEY phRegData, BOOL fRemoveItems )
2205 FIXME("%s %08x %p %d\n",
2206 debugstr_a( szScriptFile ), dwFlags, phRegData, fRemoveItems );
2207 return ERROR_CALL_NOT_IMPLEMENTED;