Release 20050930.
[wine/gsoc-2012-control.git] / dlls / msi / msi.c
blobaf1728dd81d4a41cd19227579533ff01f2f3b86d
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 "msiquery.h"
34 #include "msipriv.h"
35 #include "wincrypt.h"
36 #include "winver.h"
37 #include "winuser.h"
38 #include "wine/unicode.h"
39 #include "action.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(msi);
44 * The MSVC headers define the MSIDBOPEN_* macros cast to LPCTSTR,
45 * which is a problem because LPCTSTR isn't defined when compiling wine.
46 * To work around this problem, we need to define LPCTSTR as LPCWSTR here,
47 * and make sure to only use it in W functions.
49 #define LPCTSTR LPCWSTR
51 /* the UI level */
52 INSTALLUILEVEL gUILevel = INSTALLUILEVEL_BASIC;
53 HWND gUIhwnd = 0;
54 INSTALLUI_HANDLERA gUIHandlerA = NULL;
55 INSTALLUI_HANDLERW gUIHandlerW = NULL;
56 DWORD gUIFilter = 0;
57 LPVOID gUIContext = NULL;
58 WCHAR gszLogFile[MAX_PATH];
59 HINSTANCE msi_hInstance;
61 static const WCHAR installerW[] = {'\\','I','n','s','t','a','l','l','e','r',0};
63 UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct)
65 UINT r;
66 LPWSTR szwProd = NULL;
68 TRACE("%s %p\n",debugstr_a(szProduct), phProduct);
70 if( szProduct )
72 szwProd = strdupAtoW( szProduct );
73 if( !szwProd )
74 return ERROR_OUTOFMEMORY;
77 r = MsiOpenProductW( szwProd, phProduct );
79 msi_free( szwProd );
81 return r;
84 static UINT MSI_OpenProductW( LPCWSTR szProduct, MSIPACKAGE **ppackage )
86 LPWSTR path = NULL;
87 UINT r;
88 HKEY hKeyProduct = NULL;
89 DWORD count, type;
91 TRACE("%s %p\n", debugstr_w(szProduct), ppackage );
93 r = MSIREG_OpenUninstallKey(szProduct,&hKeyProduct,FALSE);
94 if( r != ERROR_SUCCESS )
96 r = ERROR_UNKNOWN_PRODUCT;
97 goto end;
100 /* find the size of the path */
101 type = count = 0;
102 r = RegQueryValueExW( hKeyProduct, INSTALLPROPERTY_LOCALPACKAGEW,
103 NULL, &type, NULL, &count );
104 if( r != ERROR_SUCCESS )
106 r = ERROR_UNKNOWN_PRODUCT;
107 goto end;
110 /* now alloc and fetch the path of the database to open */
111 path = msi_alloc( count );
112 if( !path )
113 goto end;
115 r = RegQueryValueExW( hKeyProduct, INSTALLPROPERTY_LOCALPACKAGEW,
116 NULL, &type, (LPBYTE) path, &count );
117 if( r != ERROR_SUCCESS )
119 r = ERROR_UNKNOWN_PRODUCT;
120 goto end;
123 r = MSI_OpenPackageW( path, ppackage );
125 end:
126 msi_free( path );
127 if( hKeyProduct )
128 RegCloseKey( hKeyProduct );
130 return r;
133 UINT WINAPI MsiOpenProductW( LPCWSTR szProduct, MSIHANDLE *phProduct )
135 MSIPACKAGE *package = NULL;
136 UINT r;
138 r = MSI_OpenProductW( szProduct, &package );
139 if( r == ERROR_SUCCESS )
141 *phProduct = alloc_msihandle( &package->hdr );
142 msiobj_release( &package->hdr );
144 return r;
147 UINT WINAPI MsiAdvertiseProductA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
148 LPCSTR szTransforms, LANGID lgidLanguage)
150 FIXME("%s %s %s %08x\n",debugstr_a(szPackagePath),
151 debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage);
152 return ERROR_CALL_NOT_IMPLEMENTED;
155 UINT WINAPI MsiAdvertiseProductW(LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
156 LPCWSTR szTransforms, LANGID lgidLanguage)
158 FIXME("%s %s %s %08x\n",debugstr_w(szPackagePath),
159 debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage);
160 return ERROR_CALL_NOT_IMPLEMENTED;
163 UINT WINAPI MsiAdvertiseProductExA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
164 LPCSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
166 FIXME("%s %s %s %08x %08lx %08lx\n", debugstr_a(szPackagePath),
167 debugstr_a(szScriptfilePath), debugstr_a(szTransforms),
168 lgidLanguage, dwPlatform, dwOptions);
169 return ERROR_CALL_NOT_IMPLEMENTED;
172 UINT WINAPI MsiAdvertiseProductExW( LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
173 LPCWSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
175 FIXME("%s %s %s %08x %08lx %08lx\n", debugstr_w(szPackagePath),
176 debugstr_w(szScriptfilePath), debugstr_w(szTransforms),
177 lgidLanguage, dwPlatform, dwOptions);
178 return ERROR_CALL_NOT_IMPLEMENTED;
181 UINT WINAPI MsiInstallProductA(LPCSTR szPackagePath, LPCSTR szCommandLine)
183 LPWSTR szwPath = NULL, szwCommand = NULL;
184 UINT r = ERROR_OUTOFMEMORY;
186 TRACE("%s %s\n",debugstr_a(szPackagePath), debugstr_a(szCommandLine));
188 if( szPackagePath )
190 szwPath = strdupAtoW( szPackagePath );
191 if( !szwPath )
192 goto end;
195 if( szCommandLine )
197 szwCommand = strdupAtoW( szCommandLine );
198 if( !szwCommand )
199 goto end;
202 r = MsiInstallProductW( szwPath, szwCommand );
204 end:
205 msi_free( szwPath );
206 msi_free( szwCommand );
208 return r;
211 UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
213 MSIPACKAGE *package = NULL;
214 UINT r;
216 FIXME("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine));
218 r = MSI_OpenPackageW( szPackagePath, &package );
219 if (r == ERROR_SUCCESS)
221 r = MSI_InstallPackage( package, szPackagePath, szCommandLine );
222 msiobj_release( &package->hdr );
225 return r;
228 UINT WINAPI MsiReinstallProductA(LPCSTR szProduct, DWORD dwReinstallMode)
230 FIXME("%s %08lx\n", debugstr_a(szProduct), dwReinstallMode);
231 return ERROR_CALL_NOT_IMPLEMENTED;
234 UINT WINAPI MsiReinstallProductW(LPCWSTR szProduct, DWORD dwReinstallMode)
236 FIXME("%s %08lx\n", debugstr_w(szProduct), dwReinstallMode);
237 return ERROR_CALL_NOT_IMPLEMENTED;
240 UINT WINAPI MsiApplyPatchA(LPCSTR szPatchPackage, LPCSTR szInstallPackage,
241 INSTALLTYPE eInstallType, LPCSTR szCommandLine)
243 FIXME("%s %s %d %s\n", debugstr_a(szPatchPackage), debugstr_a(szInstallPackage),
244 eInstallType, debugstr_a(szCommandLine));
245 return ERROR_CALL_NOT_IMPLEMENTED;
248 UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage,
249 INSTALLTYPE eInstallType, LPCWSTR szCommandLine)
251 FIXME("%s %s %d %s\n", debugstr_w(szPatchPackage), debugstr_w(szInstallPackage),
252 eInstallType, debugstr_w(szCommandLine));
253 return ERROR_CALL_NOT_IMPLEMENTED;
256 UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
257 INSTALLSTATE eInstallState, LPCWSTR szCommandLine)
259 MSIPACKAGE* package = NULL;
260 UINT r;
261 DWORD sz;
262 WCHAR sourcepath[MAX_PATH];
263 WCHAR filename[MAX_PATH];
264 static const WCHAR szInstalled[] = {
265 ' ','I','n','s','t','a','l','l','e','d','=','1',0};
266 LPWSTR commandline;
268 FIXME("%s %d %d %s\n",debugstr_w(szProduct), iInstallLevel, eInstallState,
269 debugstr_w(szCommandLine));
271 if (eInstallState != INSTALLSTATE_LOCAL &&
272 eInstallState != INSTALLSTATE_DEFAULT)
274 FIXME("Not implemented for anything other than local installs\n");
275 return ERROR_CALL_NOT_IMPLEMENTED;
278 sz = sizeof(sourcepath);
279 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
280 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath,
281 &sz);
283 sz = sizeof(filename);
284 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
285 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
287 lstrcatW(sourcepath,filename);
290 * ok 1, we need to find the msi file for this product.
291 * 2, find the source dir for the files
292 * 3, do the configure/install.
293 * 4, cleanupany runonce entry.
296 r = MSI_OpenProductW( szProduct, &package );
297 if (r != ERROR_SUCCESS)
298 return r;
300 sz = lstrlenW(szInstalled) + 1;
302 if (szCommandLine)
303 sz += lstrlenW(szCommandLine);
305 commandline = msi_alloc(sz * sizeof(WCHAR));
306 if (!commandline )
308 r = ERROR_OUTOFMEMORY;
309 goto end;
312 commandline[0] = 0;
313 if (szCommandLine)
314 lstrcpyW(commandline,szCommandLine);
316 if (MsiQueryProductStateW(szProduct) != INSTALLSTATE_UNKNOWN)
317 lstrcatW(commandline,szInstalled);
319 r = MSI_InstallPackage( package, sourcepath, commandline );
321 msi_free(commandline);
323 end:
324 msiobj_release( &package->hdr );
326 return r;
329 UINT WINAPI MsiConfigureProductExA(LPCSTR szProduct, int iInstallLevel,
330 INSTALLSTATE eInstallState, LPCSTR szCommandLine)
332 LPWSTR szwProduct = NULL;
333 LPWSTR szwCommandLine = NULL;
334 UINT r = ERROR_OUTOFMEMORY;
336 if( szProduct )
338 szwProduct = strdupAtoW( szProduct );
339 if( !szwProduct )
340 goto end;
343 if( szCommandLine)
345 szwCommandLine = strdupAtoW( szCommandLine );
346 if( !szwCommandLine)
347 goto end;
350 r = MsiConfigureProductExW( szwProduct, iInstallLevel, eInstallState,
351 szwCommandLine );
352 end:
353 msi_free( szwProduct );
354 msi_free( szwCommandLine);
356 return r;
359 UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel,
360 INSTALLSTATE eInstallState)
362 LPWSTR szwProduct = NULL;
363 UINT r;
365 TRACE("%s %d %d\n",debugstr_a(szProduct), iInstallLevel, eInstallState);
367 if( szProduct )
369 szwProduct = strdupAtoW( szProduct );
370 if( !szwProduct )
371 return ERROR_OUTOFMEMORY;
374 r = MsiConfigureProductW( szwProduct, iInstallLevel, eInstallState );
375 msi_free( szwProduct );
377 return r;
380 UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel,
381 INSTALLSTATE eInstallState)
383 FIXME("%s %d %d\n", debugstr_w(szProduct), iInstallLevel, eInstallState);
385 return MsiConfigureProductExW(szProduct, iInstallLevel, eInstallState, NULL);
388 UINT WINAPI MsiGetProductCodeA(LPCSTR szComponent, LPSTR szBuffer)
390 LPWSTR szwComponent = NULL;
391 UINT r;
392 WCHAR szwBuffer[GUID_SIZE];
394 TRACE("%s %s\n",debugstr_a(szComponent), debugstr_a(szBuffer));
396 if( szComponent )
398 szwComponent = strdupAtoW( szComponent );
399 if( !szwComponent )
400 return ERROR_OUTOFMEMORY;
403 r = MsiGetProductCodeW( szwComponent, szwBuffer );
405 if( ERROR_SUCCESS == r )
406 WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, GUID_SIZE, NULL, NULL);
408 msi_free( szwComponent );
410 return r;
413 UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer)
415 UINT rc;
416 HKEY hkey;
417 WCHAR szSquished[GUID_SIZE];
418 DWORD sz = GUID_SIZE;
419 static const WCHAR szPermKey[] =
420 { '0','0','0','0','0','0','0','0','0','0','0','0',
421 '0','0','0','0','0','0','0', '0','0','0','0','0',
422 '0','0','0','0','0','0','0','0',0};
424 TRACE("%s %p\n",debugstr_w(szComponent), szBuffer);
426 if (NULL == szComponent)
427 return ERROR_INVALID_PARAMETER;
429 rc = MSIREG_OpenComponentsKey( szComponent, &hkey, FALSE);
430 if (rc != ERROR_SUCCESS)
431 return ERROR_UNKNOWN_COMPONENT;
433 rc = RegEnumValueW(hkey, 0, szSquished, &sz, NULL, NULL, NULL, NULL);
434 if (rc == ERROR_SUCCESS && strcmpW(szSquished,szPermKey)==0)
436 sz = GUID_SIZE;
437 rc = RegEnumValueW(hkey, 1, szSquished, &sz, NULL, NULL, NULL, NULL);
440 RegCloseKey(hkey);
442 if (rc != ERROR_SUCCESS)
443 return ERROR_INSTALL_FAILURE;
445 unsquash_guid(szSquished, szBuffer);
446 return ERROR_SUCCESS;
449 UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute,
450 LPSTR szBuffer, DWORD *pcchValueBuf)
452 LPWSTR szwProduct = NULL, szwAttribute = NULL, szwBuffer = NULL;
453 UINT r = ERROR_OUTOFMEMORY;
454 DWORD pcchwValueBuf = 0;
456 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szAttribute),
457 szBuffer, pcchValueBuf);
459 if( szProduct )
461 szwProduct = strdupAtoW( szProduct );
462 if( !szwProduct )
463 goto end;
466 if( szAttribute )
468 szwAttribute = strdupAtoW( szAttribute );
469 if( !szwAttribute )
470 goto end;
473 if( szBuffer )
475 szwBuffer = msi_alloc( (*pcchValueBuf) * sizeof(WCHAR) );
476 pcchwValueBuf = *pcchValueBuf;
477 if( !szwBuffer )
478 goto end;
481 r = MsiGetProductInfoW( szwProduct, szwAttribute, szwBuffer,
482 &pcchwValueBuf );
484 if( ERROR_SUCCESS == r )
486 INT old_len = *pcchValueBuf;
487 *pcchValueBuf = WideCharToMultiByte(CP_ACP, 0, szwBuffer, pcchwValueBuf,
488 szBuffer, *pcchValueBuf, NULL, NULL);
489 if (old_len > *pcchValueBuf)
490 szBuffer[*pcchValueBuf]=0;
493 end:
494 msi_free( szwProduct );
495 msi_free( szwAttribute );
496 msi_free( szwBuffer );
498 return r;
501 UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute,
502 LPWSTR szBuffer, DWORD *pcchValueBuf)
504 MSIHANDLE hProduct;
505 UINT r;
506 static const WCHAR szProductVersion[] =
507 {'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0};
508 static const WCHAR szProductLanguage[] =
509 {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
511 FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szAttribute),
512 szBuffer, pcchValueBuf);
514 if (NULL != szBuffer && NULL == pcchValueBuf)
515 return ERROR_INVALID_PARAMETER;
516 if (NULL == szProduct || NULL == szAttribute)
517 return ERROR_INVALID_PARAMETER;
519 /* check for special properties */
520 if (strcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW)==0)
522 HKEY hkey;
523 WCHAR squished[GUID_SIZE];
524 WCHAR package[200];
525 DWORD sz = sizeof(squished);
527 r = MSIREG_OpenUserProductsKey(szProduct, &hkey, FALSE);
528 if (r != ERROR_SUCCESS)
529 return ERROR_UNKNOWN_PRODUCT;
531 r = RegQueryValueExW(hkey, INSTALLPROPERTY_PACKAGECODEW, NULL, NULL,
532 (LPBYTE)squished, &sz);
533 if (r != ERROR_SUCCESS)
535 RegCloseKey(hkey);
536 return ERROR_UNKNOWN_PRODUCT;
539 unsquash_guid(squished, package);
540 *pcchValueBuf = strlenW(package);
541 if (strlenW(package) > *pcchValueBuf)
543 RegCloseKey(hkey);
544 return ERROR_MORE_DATA;
546 else
547 strcpyW(szBuffer, package);
549 RegCloseKey(hkey);
550 r = ERROR_SUCCESS;
552 else if (strcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW)==0)
554 r = MsiOpenProductW(szProduct, &hProduct);
555 if (ERROR_SUCCESS != r)
556 return r;
558 r = MsiGetPropertyW(hProduct, szProductVersion, szBuffer, pcchValueBuf);
559 MsiCloseHandle(hProduct);
561 else if (strcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW)==0)
563 FIXME("0 (zero) if advertised or per user , 1(one) if per machine.\n");
564 if (szBuffer)
566 szBuffer[0] = '1';
567 szBuffer[1] = 0;
569 if (pcchValueBuf)
570 *pcchValueBuf = 1;
571 r = ERROR_SUCCESS;
573 else if (strcmpW(szAttribute, INSTALLPROPERTY_LANGUAGEW)==0)
575 r = MsiOpenProductW(szProduct, &hProduct);
576 if (ERROR_SUCCESS != r)
577 return r;
579 r = MsiGetPropertyW(hProduct, szProductLanguage, szBuffer, pcchValueBuf);
580 MsiCloseHandle(hProduct);
582 else
584 r = MsiOpenProductW(szProduct, &hProduct);
585 if (ERROR_SUCCESS != r)
586 return r;
588 r = MsiGetPropertyW(hProduct, szAttribute, szBuffer, pcchValueBuf);
589 MsiCloseHandle(hProduct);
592 return r;
595 UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes)
597 LPWSTR szwLogFile = NULL;
598 UINT r;
600 TRACE("%08lx %s %08lx\n", dwLogMode, debugstr_a(szLogFile), attributes);
602 if( szLogFile )
604 szwLogFile = strdupAtoW( szLogFile );
605 if( !szwLogFile )
606 return ERROR_OUTOFMEMORY;
608 r = MsiEnableLogW( dwLogMode, szwLogFile, attributes );
609 msi_free( szwLogFile );
610 return r;
613 UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, DWORD attributes)
615 HANDLE file = INVALID_HANDLE_VALUE;
617 TRACE("%08lx %s %08lx\n", dwLogMode, debugstr_w(szLogFile), attributes);
619 lstrcpyW(gszLogFile,szLogFile);
620 if (!(attributes & INSTALLLOGATTRIBUTES_APPEND))
621 DeleteFileW(szLogFile);
622 file = CreateFileW(szLogFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
623 FILE_ATTRIBUTE_NORMAL, NULL);
624 if (file != INVALID_HANDLE_VALUE)
625 CloseHandle(file);
626 else
627 ERR("Unable to enable log %s\n",debugstr_w(szLogFile));
629 return ERROR_SUCCESS;
632 INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct)
634 LPWSTR szwProduct = NULL;
635 INSTALLSTATE r;
637 if( szProduct )
639 szwProduct = strdupAtoW( szProduct );
640 if( !szwProduct )
641 return ERROR_OUTOFMEMORY;
643 r = MsiQueryProductStateW( szwProduct );
644 msi_free( szwProduct );
645 return r;
648 INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct)
650 UINT rc;
651 INSTALLSTATE rrc = INSTALLSTATE_UNKNOWN;
652 HKEY hkey = 0;
653 static const WCHAR szWindowsInstaller[] = {
654 'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0 };
655 DWORD sz;
657 TRACE("%s\n", debugstr_w(szProduct));
659 rc = MSIREG_OpenUserProductsKey(szProduct,&hkey,FALSE);
660 if (rc != ERROR_SUCCESS)
661 goto end;
663 RegCloseKey(hkey);
665 rc = MSIREG_OpenUninstallKey(szProduct,&hkey,FALSE);
666 if (rc != ERROR_SUCCESS)
667 goto end;
669 sz = sizeof(rrc);
670 rc = RegQueryValueExW(hkey,szWindowsInstaller,NULL,NULL,(LPVOID)&rrc, &sz);
671 if (rc != ERROR_SUCCESS)
672 goto end;
674 switch (rrc)
676 case 1:
677 /* default */
678 rrc = INSTALLSTATE_DEFAULT;
679 break;
680 default:
681 FIXME("Unknown install state read from registry (%i)\n",rrc);
682 rrc = INSTALLSTATE_UNKNOWN;
683 break;
685 end:
686 RegCloseKey(hkey);
687 return rrc;
690 INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd)
692 INSTALLUILEVEL old = gUILevel;
693 HWND oldwnd = gUIhwnd;
695 TRACE("%08x %p\n", dwUILevel, phWnd);
697 gUILevel = dwUILevel;
698 if (phWnd)
700 gUIhwnd = *phWnd;
701 *phWnd = oldwnd;
703 return old;
706 INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler,
707 DWORD dwMessageFilter, LPVOID pvContext)
709 INSTALLUI_HANDLERA prev = gUIHandlerA;
711 TRACE("%p %lx %p\n",puiHandler, dwMessageFilter,pvContext);
712 gUIHandlerA = puiHandler;
713 gUIFilter = dwMessageFilter;
714 gUIContext = pvContext;
716 return prev;
719 INSTALLUI_HANDLERW WINAPI MsiSetExternalUIW(INSTALLUI_HANDLERW puiHandler,
720 DWORD dwMessageFilter, LPVOID pvContext)
722 INSTALLUI_HANDLERW prev = gUIHandlerW;
724 TRACE("%p %lx %p\n",puiHandler,dwMessageFilter,pvContext);
725 gUIHandlerW = puiHandler;
726 gUIFilter = dwMessageFilter;
727 gUIContext = pvContext;
729 return prev;
732 /******************************************************************
733 * MsiLoadStringW [MSI.@]
735 * Loads a string from MSI's string resources.
737 * PARAMS
739 * handle [I] only -1 is handled currently
740 * id [I] id of the string to be loaded
741 * lpBuffer [O] buffer for the string to be written to
742 * nBufferMax [I] maximum size of the buffer in characters
743 * lang [I] the preferred language for the string
745 * RETURNS
747 * If successful, this function returns the language id of the string loaded
748 * If the function fails, the function returns zero.
750 * NOTES
752 * The type of the first parameter is unknown. LoadString's prototype
753 * suggests that it might be a module handle. I have made it an MSI handle
754 * for starters, as -1 is an invalid MSI handle, but not an invalid module
755 * handle. Maybe strings can be stored in an MSI database somehow.
757 LANGID WINAPI MsiLoadStringW( MSIHANDLE handle, UINT id, LPWSTR lpBuffer,
758 int nBufferMax, LANGID lang )
760 HRSRC hres;
761 HGLOBAL hResData;
762 LPWSTR p;
763 DWORD i, len;
765 TRACE("%ld %u %p %d %d\n", handle, id, lpBuffer, nBufferMax, lang);
767 if( handle != -1 )
768 FIXME("don't know how to deal with handle = %08lx\n", handle);
770 if( !lang )
771 lang = GetUserDefaultLangID();
773 hres = FindResourceExW( msi_hInstance, (LPCWSTR) RT_STRING,
774 (LPWSTR)1, lang );
775 if( !hres )
776 return 0;
777 hResData = LoadResource( msi_hInstance, hres );
778 if( !hResData )
779 return 0;
780 p = LockResource( hResData );
781 if( !p )
782 return 0;
784 for (i = 0; i < (id&0xf); i++)
785 p += *p + 1;
786 len = *p;
788 if( nBufferMax <= len )
789 return 0;
791 memcpy( lpBuffer, p+1, len * sizeof(WCHAR));
792 lpBuffer[ len ] = 0;
794 TRACE("found -> %s\n", debugstr_w(lpBuffer));
796 return lang;
799 LANGID WINAPI MsiLoadStringA( MSIHANDLE handle, UINT id, LPSTR lpBuffer,
800 int nBufferMax, LANGID lang )
802 LPWSTR bufW;
803 LANGID r;
804 DWORD len;
806 bufW = msi_alloc(nBufferMax*sizeof(WCHAR));
807 r = MsiLoadStringW(handle, id, bufW, nBufferMax, lang);
808 if( r )
810 len = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL );
811 if( len <= nBufferMax )
812 WideCharToMultiByte( CP_ACP, 0, bufW, -1,
813 lpBuffer, nBufferMax, NULL, NULL );
814 else
815 r = 0;
817 msi_free(bufW);
818 return r;
821 INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf,
822 DWORD *pcchBuf)
824 FIXME("%s %p %p\n", debugstr_a(szComponent), lpPathBuf, pcchBuf);
825 return INSTALLSTATE_UNKNOWN;
828 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPWSTR lpPathBuf,
829 DWORD *pcchBuf)
831 FIXME("%s %p %p\n", debugstr_w(szComponent), lpPathBuf, pcchBuf);
832 return INSTALLSTATE_UNKNOWN;
835 UINT WINAPI MsiMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType,
836 WORD wLanguageId, DWORD f)
838 FIXME("%p %s %s %u %08x %08lx\n",hWnd,debugstr_a(lpText),debugstr_a(lpCaption),
839 uType,wLanguageId,f);
840 return ERROR_CALL_NOT_IMPLEMENTED;
843 UINT WINAPI MsiMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType,
844 WORD wLanguageId, DWORD f)
846 FIXME("%p %s %s %u %08x %08lx\n",hWnd,debugstr_w(lpText),debugstr_w(lpCaption),
847 uType,wLanguageId,f);
848 return ERROR_CALL_NOT_IMPLEMENTED;
851 UINT WINAPI MsiProvideAssemblyA( LPCSTR szAssemblyName, LPCSTR szAppContext,
852 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf,
853 DWORD* pcchPathBuf )
855 FIXME("%s %s %08lx %08lx %p %p\n", debugstr_a(szAssemblyName),
856 debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
857 pcchPathBuf);
858 return ERROR_CALL_NOT_IMPLEMENTED;
861 UINT WINAPI MsiProvideAssemblyW( LPCWSTR szAssemblyName, LPCWSTR szAppContext,
862 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf,
863 DWORD* pcchPathBuf )
865 FIXME("%s %s %08lx %08lx %p %p\n", debugstr_w(szAssemblyName),
866 debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
867 pcchPathBuf);
868 return ERROR_CALL_NOT_IMPLEMENTED;
871 UINT WINAPI MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor,
872 LPSTR szPath, DWORD *pcchPath, DWORD *pcchArgs )
874 FIXME("%s %p %p %p\n", debugstr_a(szDescriptor), szPath, pcchPath, pcchArgs );
875 return ERROR_CALL_NOT_IMPLEMENTED;
878 UINT WINAPI MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor,
879 LPWSTR szPath, DWORD *pcchPath, DWORD *pcchArgs )
881 FIXME("%s %p %p %p\n", debugstr_w(szDescriptor), szPath, pcchPath, pcchArgs );
882 return ERROR_CALL_NOT_IMPLEMENTED;
885 HRESULT WINAPI MsiGetFileSignatureInformationA( LPCSTR szSignedObjectPath,
886 DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData,
887 DWORD* pcbHashData)
889 FIXME("%s %08lx %p %p %p\n", debugstr_a(szSignedObjectPath), dwFlags,
890 ppcCertContext, pbHashData, pcbHashData);
891 return ERROR_CALL_NOT_IMPLEMENTED;
894 HRESULT WINAPI MsiGetFileSignatureInformationW( LPCWSTR szSignedObjectPath,
895 DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData,
896 DWORD* pcbHashData)
898 FIXME("%s %08lx %p %p %p\n", debugstr_w(szSignedObjectPath), dwFlags,
899 ppcCertContext, pbHashData, pcbHashData);
900 return ERROR_CALL_NOT_IMPLEMENTED;
903 UINT WINAPI MsiGetProductPropertyA( MSIHANDLE hProduct, LPCSTR szProperty,
904 LPSTR szValue, DWORD *pccbValue )
906 FIXME("%ld %s %p %p\n", hProduct, debugstr_a(szProperty), szValue, pccbValue);
907 return ERROR_CALL_NOT_IMPLEMENTED;
910 UINT WINAPI MsiGetProductPropertyW( MSIHANDLE hProduct, LPCWSTR szProperty,
911 LPWSTR szValue, DWORD *pccbValue )
913 FIXME("%ld %s %p %p\n", hProduct, debugstr_w(szProperty), szValue, pccbValue);
914 return ERROR_CALL_NOT_IMPLEMENTED;
917 UINT WINAPI MsiVerifyPackageA( LPCSTR szPackage )
919 UINT r;
920 LPWSTR szPack = NULL;
922 TRACE("%s\n", debugstr_a(szPackage) );
924 if( szPackage )
926 szPack = strdupAtoW( szPackage );
927 if( !szPack )
928 return ERROR_OUTOFMEMORY;
931 r = MsiVerifyPackageW( szPack );
933 msi_free( szPack );
935 return r;
938 UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage )
940 MSIHANDLE handle;
941 UINT r;
943 TRACE("%s\n", debugstr_w(szPackage) );
945 r = MsiOpenDatabaseW( szPackage, MSIDBOPEN_READONLY, &handle );
946 MsiCloseHandle( handle );
948 return r;
951 INSTALLSTATE WINAPI MsiGetComponentPathA(LPCSTR szProduct, LPCSTR szComponent,
952 LPSTR lpPathBuf, DWORD* pcchBuf)
954 LPWSTR szwProduct = NULL, szwComponent = NULL, lpwPathBuf= NULL;
955 INSTALLSTATE rc;
956 UINT incoming_len;
958 if( szProduct )
960 szwProduct = strdupAtoW( szProduct );
961 if( !szwProduct)
962 return ERROR_OUTOFMEMORY;
965 if( szComponent )
967 szwComponent = strdupAtoW( szComponent );
968 if( !szwComponent )
970 msi_free( szwProduct);
971 return ERROR_OUTOFMEMORY;
975 if( pcchBuf && *pcchBuf > 0 )
977 lpwPathBuf = msi_alloc( *pcchBuf * sizeof(WCHAR));
978 incoming_len = *pcchBuf;
980 else
982 lpwPathBuf = NULL;
983 incoming_len = 0;
986 rc = MsiGetComponentPathW(szwProduct, szwComponent, lpwPathBuf, pcchBuf);
988 msi_free( szwProduct);
989 msi_free( szwComponent);
990 if (lpwPathBuf)
992 if (rc != INSTALLSTATE_UNKNOWN)
993 WideCharToMultiByte(CP_ACP, 0, lpwPathBuf, incoming_len,
994 lpPathBuf, incoming_len, NULL, NULL);
995 msi_free( lpwPathBuf);
998 return rc;
1001 INSTALLSTATE WINAPI MsiGetComponentPathW(LPCWSTR szProduct, LPCWSTR szComponent,
1002 LPWSTR lpPathBuf, DWORD* pcchBuf)
1004 WCHAR squished_pc[GUID_SIZE];
1005 UINT rc;
1006 INSTALLSTATE rrc = INSTALLSTATE_UNKNOWN;
1007 HKEY hkey = 0;
1008 LPWSTR path = NULL;
1009 DWORD sz, type;
1011 TRACE("%s %s %p %p\n", debugstr_w(szProduct),
1012 debugstr_w(szComponent), lpPathBuf, pcchBuf);
1014 if( lpPathBuf && !pcchBuf )
1015 return INSTALLSTATE_INVALIDARG;
1017 squash_guid(szProduct,squished_pc);
1019 rc = MSIREG_OpenProductsKey( szProduct, &hkey, FALSE);
1020 if( rc != ERROR_SUCCESS )
1021 goto end;
1023 RegCloseKey(hkey);
1025 rc = MSIREG_OpenComponentsKey( szComponent, &hkey, FALSE);
1026 if( rc != ERROR_SUCCESS )
1027 goto end;
1029 sz = 0;
1030 type = 0;
1031 rc = RegQueryValueExW( hkey, squished_pc, NULL, &type, NULL, &sz );
1032 if( rc != ERROR_SUCCESS )
1033 goto end;
1034 if( type != REG_SZ )
1035 goto end;
1037 sz += sizeof(WCHAR);
1038 path = msi_alloc( sz );
1039 if( !path )
1040 goto end;
1042 rc = RegQueryValueExW( hkey, squished_pc, NULL, NULL, (LPVOID) path, &sz );
1043 if( rc != ERROR_SUCCESS )
1044 goto end;
1046 TRACE("found path of (%s:%s)(%s)\n", debugstr_w(szComponent),
1047 debugstr_w(szProduct), debugstr_w(path));
1049 if (path[0]=='0')
1051 FIXME("Registry entry.. check entry\n");
1052 rrc = INSTALLSTATE_LOCAL;
1054 else
1056 /* PROBABLY a file */
1057 if ( GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES )
1058 rrc = INSTALLSTATE_LOCAL;
1059 else
1060 rrc = INSTALLSTATE_ABSENT;
1063 if( pcchBuf )
1065 sz = sz / sizeof(WCHAR);
1066 if( *pcchBuf >= sz )
1067 lstrcpyW( lpPathBuf, path );
1068 *pcchBuf = sz;
1071 end:
1072 msi_free(path );
1073 RegCloseKey(hkey);
1074 return rrc;
1077 /******************************************************************
1078 * MsiQueryFeatureStateA [MSI.@]
1080 INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature)
1082 INSTALLSTATE rc;
1083 LPWSTR szwProduct= NULL;
1084 LPWSTR szwFeature= NULL;
1086 if( szProduct )
1088 szwProduct = strdupAtoW( szProduct );
1089 if( !szwProduct)
1090 return ERROR_OUTOFMEMORY;
1093 if( szFeature )
1095 szwFeature = strdupAtoW( szFeature );
1096 if( !szwFeature)
1098 msi_free( szwProduct);
1099 return ERROR_OUTOFMEMORY;
1103 rc = MsiQueryFeatureStateW(szwProduct, szwFeature);
1105 msi_free( szwProduct);
1106 msi_free( szwFeature);
1108 return rc;
1111 /******************************************************************
1112 * MsiQueryFeatureStateW [MSI.@]
1114 * This does not verify that the Feature is functional. So i am only going to
1115 * check the existence of the key in the registry. This should tell me if it is
1116 * installed.
1118 INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature)
1120 UINT rc;
1121 DWORD sz = 0;
1122 HKEY hkey;
1124 TRACE("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature));
1126 rc = MSIREG_OpenFeaturesKey(szProduct, &hkey, FALSE);
1127 if (rc != ERROR_SUCCESS)
1128 return INSTALLSTATE_UNKNOWN;
1130 rc = RegQueryValueExW( hkey, szFeature, NULL, NULL, NULL, &sz);
1131 RegCloseKey(hkey);
1133 if (rc == ERROR_SUCCESS)
1134 return INSTALLSTATE_LOCAL;
1135 else
1136 return INSTALLSTATE_ABSENT;
1139 /******************************************************************
1140 * MsiGetFileVersionA [MSI.@]
1142 UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf,
1143 DWORD* pcchVersionBuf, LPSTR lpLangBuf, DWORD* pcchLangBuf)
1145 LPWSTR szwFilePath = NULL, lpwVersionBuff = NULL, lpwLangBuff = NULL;
1146 UINT ret = ERROR_OUTOFMEMORY;
1148 if( szFilePath )
1150 szwFilePath = strdupAtoW( szFilePath );
1151 if( !szwFilePath )
1152 goto end;
1155 if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf )
1157 lpwVersionBuff = msi_alloc(*pcchVersionBuf*sizeof(WCHAR));
1158 if( !lpwVersionBuff )
1159 goto end;
1162 if( lpLangBuf && pcchLangBuf && *pcchLangBuf )
1164 lpwLangBuff = msi_alloc(*pcchVersionBuf*sizeof(WCHAR));
1165 if( !lpwLangBuff )
1166 goto end;
1169 ret = MsiGetFileVersionW(szwFilePath, lpwVersionBuff, pcchVersionBuf,
1170 lpwLangBuff, pcchLangBuf);
1172 if( lpwVersionBuff )
1173 WideCharToMultiByte(CP_ACP, 0, lpwVersionBuff, -1,
1174 lpVersionBuf, *pcchVersionBuf, NULL, NULL);
1175 if( lpwLangBuff )
1176 WideCharToMultiByte(CP_ACP, 0, lpwLangBuff, -1,
1177 lpLangBuf, *pcchLangBuf, NULL, NULL);
1179 end:
1180 msi_free(szwFilePath);
1181 msi_free(lpwVersionBuff);
1182 msi_free(lpwLangBuff);
1184 return ret;
1187 /******************************************************************
1188 * MsiGetFileVersionW [MSI.@]
1190 UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf,
1191 DWORD* pcchVersionBuf, LPWSTR lpLangBuf, DWORD* pcchLangBuf)
1193 static const WCHAR szVersionResource[] = {'\\',0};
1194 static const WCHAR szVersionFormat[] = {
1195 '%','d','.','%','d','.','%','d','.','%','d',0};
1196 static const WCHAR szLangFormat[] = {'%','d',0};
1197 UINT ret = 0;
1198 DWORD dwVerLen;
1199 LPVOID lpVer = NULL;
1200 VS_FIXEDFILEINFO *ffi;
1201 UINT puLen;
1202 WCHAR tmp[32];
1204 TRACE("%s %p %ld %p %ld\n", debugstr_w(szFilePath),
1205 lpVersionBuf, pcchVersionBuf?*pcchVersionBuf:0,
1206 lpLangBuf, pcchLangBuf?*pcchLangBuf:0);
1208 dwVerLen = GetFileVersionInfoSizeW(szFilePath, NULL);
1209 if( !dwVerLen )
1210 return GetLastError();
1212 lpVer = msi_alloc(dwVerLen);
1213 if( !lpVer )
1215 ret = ERROR_OUTOFMEMORY;
1216 goto end;
1219 if( !GetFileVersionInfoW(szFilePath, 0, dwVerLen, lpVer) )
1221 ret = GetLastError();
1222 goto end;
1224 if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf )
1226 if( VerQueryValueW(lpVer, szVersionResource, (LPVOID*)&ffi, &puLen) &&
1227 (puLen > 0) )
1229 wsprintfW(tmp, szVersionFormat,
1230 HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS),
1231 HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS));
1232 lstrcpynW(lpVersionBuf, tmp, *pcchVersionBuf);
1233 *pcchVersionBuf = lstrlenW(lpVersionBuf);
1235 else
1237 *lpVersionBuf = 0;
1238 *pcchVersionBuf = 0;
1242 if( lpLangBuf && pcchLangBuf && *pcchLangBuf )
1244 DWORD lang = GetUserDefaultLangID();
1246 FIXME("Retrieve language from file\n");
1247 wsprintfW(tmp, szLangFormat, lang);
1248 lstrcpynW(lpLangBuf, tmp, *pcchLangBuf);
1249 *pcchLangBuf = lstrlenW(lpLangBuf);
1252 end:
1253 msi_free(lpVer);
1254 return ret;
1258 /******************************************************************
1259 * DllMain
1261 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
1263 switch(fdwReason)
1265 case DLL_PROCESS_ATTACH:
1266 msi_hInstance = hinstDLL;
1267 DisableThreadLibraryCalls(hinstDLL);
1268 msi_dialog_register_class();
1269 break;
1270 case DLL_PROCESS_DETACH:
1271 msi_dialog_unregister_class();
1272 /* FIXME: Cleanup */
1273 break;
1275 return TRUE;
1278 typedef struct tagIClassFactoryImpl
1280 const IClassFactoryVtbl *lpVtbl;
1281 } IClassFactoryImpl;
1283 static HRESULT WINAPI MsiCF_QueryInterface(LPCLASSFACTORY iface,
1284 REFIID riid,LPVOID *ppobj)
1286 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
1287 FIXME("%p %s %p\n",This,debugstr_guid(riid),ppobj);
1288 return E_NOINTERFACE;
1291 static ULONG WINAPI MsiCF_AddRef(LPCLASSFACTORY iface)
1293 return 2;
1296 static ULONG WINAPI MsiCF_Release(LPCLASSFACTORY iface)
1298 return 1;
1301 static HRESULT WINAPI MsiCF_CreateInstance(LPCLASSFACTORY iface,
1302 LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj)
1304 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
1306 FIXME("%p %p %s %p\n", This, pOuter, debugstr_guid(riid), ppobj);
1307 return E_FAIL;
1310 static HRESULT WINAPI MsiCF_LockServer(LPCLASSFACTORY iface, BOOL dolock)
1312 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
1314 FIXME("%p %d\n", This, dolock);
1315 return S_OK;
1318 static const IClassFactoryVtbl MsiCF_Vtbl =
1320 MsiCF_QueryInterface,
1321 MsiCF_AddRef,
1322 MsiCF_Release,
1323 MsiCF_CreateInstance,
1324 MsiCF_LockServer
1327 static IClassFactoryImpl Msi_CF = { &MsiCF_Vtbl };
1329 /******************************************************************
1330 * DllGetClassObject [MSI.@]
1332 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
1334 TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
1336 if( IsEqualCLSID (rclsid, &CLSID_IMsiServer) ||
1337 IsEqualCLSID (rclsid, &CLSID_IMsiServerMessage) ||
1338 IsEqualCLSID (rclsid, &CLSID_IMsiServerX1) ||
1339 IsEqualCLSID (rclsid, &CLSID_IMsiServerX2) ||
1340 IsEqualCLSID (rclsid, &CLSID_IMsiServerX3) )
1342 *ppv = (LPVOID) &Msi_CF;
1343 return S_OK;
1345 return CLASS_E_CLASSNOTAVAILABLE;
1348 /******************************************************************
1349 * DllGetVersion [MSI.@]
1351 HRESULT WINAPI DllGetVersion(DLLVERSIONINFO *pdvi)
1353 TRACE("%p\n",pdvi);
1355 if (pdvi->cbSize != sizeof(DLLVERSIONINFO))
1356 return E_INVALIDARG;
1358 pdvi->dwMajorVersion = MSI_MAJORVERSION;
1359 pdvi->dwMinorVersion = MSI_MINORVERSION;
1360 pdvi->dwBuildNumber = MSI_BUILDNUMBER;
1361 pdvi->dwPlatformID = 1;
1363 return S_OK;
1366 /******************************************************************
1367 * DllCanUnloadNow [MSI.@]
1369 HRESULT WINAPI DllCanUnloadNow(void)
1371 return S_FALSE;
1374 UINT WINAPI MsiGetFeatureUsageW(LPCWSTR szProduct, LPCWSTR szFeature,
1375 DWORD* pdwUseCount, WORD* pwDateUsed)
1377 FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szFeature),
1378 pdwUseCount, pwDateUsed);
1379 return ERROR_CALL_NOT_IMPLEMENTED;
1382 UINT WINAPI MsiGetFeatureUsageA(LPCSTR szProduct, LPCSTR szFeature,
1383 DWORD* pdwUseCount, WORD* pwDateUsed)
1385 FIXME("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szFeature),
1386 pdwUseCount, pwDateUsed);
1387 return ERROR_CALL_NOT_IMPLEMENTED;
1390 INSTALLSTATE WINAPI MsiUseFeatureExW(LPCWSTR szProduct, LPCWSTR szFeature,
1391 DWORD dwInstallMode, DWORD dwReserved)
1393 FIXME("%s %s %li %li\n", debugstr_w(szProduct), debugstr_w(szFeature),
1394 dwInstallMode, dwReserved);
1397 * Polls all the components of the feature to find install state and then
1398 * writes:
1399 * Software\\Microsoft\\Windows\\CurrentVersion\\
1400 * Installer\\Products\\<squishguid>\\<feature>
1401 * "Usage"=dword:........
1404 return INSTALLSTATE_LOCAL;
1407 /***********************************************************************
1408 * MsiUseFeatureExA [MSI.@]
1410 INSTALLSTATE WINAPI MsiUseFeatureExA(LPCSTR szProduct, LPCSTR szFeature,
1411 DWORD dwInstallMode, DWORD dwReserved)
1413 FIXME("%s %s %li %li\n", debugstr_a(szProduct), debugstr_a(szFeature),
1414 dwInstallMode, dwReserved);
1416 return INSTALLSTATE_LOCAL;
1419 INSTALLSTATE WINAPI MsiUseFeatureW(LPCWSTR szProduct, LPCWSTR szFeature)
1421 FIXME("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature));
1423 return INSTALLSTATE_LOCAL;
1426 INSTALLSTATE WINAPI MsiUseFeatureA(LPCSTR szProduct, LPCSTR szFeature)
1428 FIXME("%s %s\n", debugstr_a(szProduct), debugstr_a(szFeature));
1430 return INSTALLSTATE_LOCAL;
1433 UINT WINAPI MsiProvideQualifiedComponentExW(LPCWSTR szComponent,
1434 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR szProduct,
1435 DWORD Unused1, DWORD Unused2, LPWSTR lpPathBuf,
1436 DWORD* pcchPathBuf)
1438 HKEY hkey;
1439 UINT rc;
1440 LPWSTR info;
1441 DWORD sz;
1442 LPWSTR product = NULL;
1443 LPWSTR component = NULL;
1444 LPWSTR ptr;
1445 GUID clsid;
1447 TRACE("%s %s %li %s %li %li %p %p\n", debugstr_w(szComponent),
1448 debugstr_w(szQualifier), dwInstallMode, debugstr_w(szProduct),
1449 Unused1, Unused2, lpPathBuf, pcchPathBuf);
1451 rc = MSIREG_OpenUserComponentsKey(szComponent, &hkey, FALSE);
1452 if (rc != ERROR_SUCCESS)
1453 return ERROR_INDEX_ABSENT;
1455 sz = 0;
1456 rc = RegQueryValueExW( hkey, szQualifier, NULL, NULL, NULL, &sz);
1457 if (sz <= 0)
1459 RegCloseKey(hkey);
1460 return ERROR_INDEX_ABSENT;
1463 info = msi_alloc(sz);
1464 rc = RegQueryValueExW( hkey, szQualifier, NULL, NULL, (LPBYTE)info, &sz);
1465 if (rc != ERROR_SUCCESS)
1467 RegCloseKey(hkey);
1468 msi_free(info);
1469 return ERROR_INDEX_ABSENT;
1472 /* find the component */
1473 ptr = strchrW(&info[20],'>');
1474 if (ptr)
1475 ptr++;
1476 else
1478 RegCloseKey(hkey);
1479 msi_free(info);
1480 return ERROR_INDEX_ABSENT;
1483 if (!szProduct)
1485 decode_base85_guid(info,&clsid);
1486 StringFromCLSID(&clsid, &product);
1488 decode_base85_guid(ptr,&clsid);
1489 StringFromCLSID(&clsid, &component);
1491 if (!szProduct)
1492 rc = MsiGetComponentPathW(product, component, lpPathBuf, pcchPathBuf);
1493 else
1494 rc = MsiGetComponentPathW(szProduct, component, lpPathBuf, pcchPathBuf);
1496 RegCloseKey(hkey);
1497 msi_free(info);
1498 msi_free(product);
1499 msi_free(component);
1501 if (rc == INSTALLSTATE_LOCAL)
1502 return ERROR_SUCCESS;
1503 else
1504 return ERROR_FILE_NOT_FOUND;
1507 /***********************************************************************
1508 * MsiProvideQualifiedComponentW [MSI.@]
1510 UINT WINAPI MsiProvideQualifiedComponentW( LPCWSTR szComponent,
1511 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR lpPathBuf,
1512 DWORD* pcchPathBuf)
1514 return MsiProvideQualifiedComponentExW(szComponent, szQualifier,
1515 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
1518 /***********************************************************************
1519 * MsiProvideQualifiedComponentA [MSI.@]
1521 UINT WINAPI MsiProvideQualifiedComponentA( LPCSTR szComponent,
1522 LPCSTR szQualifier, DWORD dwInstallMode, LPSTR lpPathBuf,
1523 DWORD* pcchPathBuf)
1525 LPWSTR szwComponent, szwQualifier, lpwPathBuf;
1526 DWORD pcchwPathBuf;
1527 UINT rc;
1529 TRACE("%s %s %li %p %p\n",szComponent, szQualifier,
1530 dwInstallMode, lpPathBuf, pcchPathBuf);
1532 szwComponent= strdupAtoW( szComponent);
1533 szwQualifier= strdupAtoW( szQualifier);
1535 lpwPathBuf = msi_alloc(*pcchPathBuf * sizeof(WCHAR));
1537 pcchwPathBuf = *pcchPathBuf;
1539 rc = MsiProvideQualifiedComponentW(szwComponent, szwQualifier,
1540 dwInstallMode, lpwPathBuf, &pcchwPathBuf);
1542 msi_free(szwComponent);
1543 msi_free(szwQualifier);
1544 *pcchPathBuf = WideCharToMultiByte(CP_ACP, 0, lpwPathBuf, pcchwPathBuf,
1545 lpPathBuf, *pcchPathBuf, NULL, NULL);
1547 msi_free(lpwPathBuf);
1548 return rc;
1551 USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct, LPWSTR lpUserNameBuf,
1552 DWORD* pcchUserNameBuf, LPWSTR lpOrgNameBuf,
1553 DWORD* pcchOrgNameBuf, LPWSTR lpSerialBuf, DWORD* pcchSerialBuf)
1555 HKEY hkey;
1556 DWORD sz;
1557 UINT rc = ERROR_SUCCESS,rc2 = ERROR_SUCCESS;
1559 TRACE("%s %p %p %p %p %p %p\n",debugstr_w(szProduct), lpUserNameBuf,
1560 pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf,
1561 pcchSerialBuf);
1563 rc = MSIREG_OpenUninstallKey(szProduct, &hkey, FALSE);
1564 if (rc != ERROR_SUCCESS)
1565 return USERINFOSTATE_UNKNOWN;
1567 if (lpUserNameBuf)
1569 sz = *lpUserNameBuf * sizeof(WCHAR);
1570 rc = RegQueryValueExW( hkey, INSTALLPROPERTY_REGOWNERW, NULL,
1571 NULL, (LPBYTE)lpUserNameBuf,
1572 &sz);
1574 if (!lpUserNameBuf && pcchUserNameBuf)
1576 sz = 0;
1577 rc = RegQueryValueExW( hkey, INSTALLPROPERTY_REGOWNERW, NULL,
1578 NULL, NULL, &sz);
1581 if (pcchUserNameBuf)
1582 *pcchUserNameBuf = sz / sizeof(WCHAR);
1584 if (lpOrgNameBuf)
1586 sz = *pcchOrgNameBuf * sizeof(WCHAR);
1587 rc2 = RegQueryValueExW( hkey, INSTALLPROPERTY_REGCOMPANYW, NULL,
1588 NULL, (LPBYTE)lpOrgNameBuf, &sz);
1590 if (!lpOrgNameBuf && pcchOrgNameBuf)
1592 sz = 0;
1593 rc2 = RegQueryValueExW( hkey, INSTALLPROPERTY_REGCOMPANYW, NULL,
1594 NULL, NULL, &sz);
1597 if (pcchOrgNameBuf)
1598 *pcchOrgNameBuf = sz / sizeof(WCHAR);
1600 if (rc != ERROR_SUCCESS && rc != ERROR_MORE_DATA &&
1601 rc2 != ERROR_SUCCESS && rc2 != ERROR_MORE_DATA)
1603 RegCloseKey(hkey);
1604 return USERINFOSTATE_ABSENT;
1607 if (lpSerialBuf)
1609 sz = *pcchSerialBuf * sizeof(WCHAR);
1610 RegQueryValueExW( hkey, INSTALLPROPERTY_PRODUCTIDW, NULL, NULL,
1611 (LPBYTE)lpSerialBuf, &sz);
1613 if (!lpSerialBuf && pcchSerialBuf)
1615 sz = 0;
1616 rc = RegQueryValueExW( hkey, INSTALLPROPERTY_PRODUCTIDW, NULL,
1617 NULL, NULL, &sz);
1619 if (pcchSerialBuf)
1620 *pcchSerialBuf = sz / sizeof(WCHAR);
1622 RegCloseKey(hkey);
1623 return USERINFOSTATE_PRESENT;
1626 USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR szProduct, LPSTR lpUserNameBuf,
1627 DWORD* pcchUserNameBuf, LPSTR lpOrgNameBuf,
1628 DWORD* pcchOrgNameBuf, LPSTR lpSerialBuf, DWORD* pcchSerialBuf)
1630 FIXME("%s %p %p %p %p %p %p\n",debugstr_a(szProduct), lpUserNameBuf,
1631 pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf,
1632 pcchSerialBuf);
1634 return USERINFOSTATE_UNKNOWN;
1637 UINT WINAPI MsiCollectUserInfoW(LPCWSTR szProduct)
1639 MSIHANDLE handle;
1640 UINT rc;
1641 MSIPACKAGE *package;
1642 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
1644 TRACE("(%s)\n",debugstr_w(szProduct));
1646 rc = MsiOpenProductW(szProduct,&handle);
1647 if (rc != ERROR_SUCCESS)
1648 return ERROR_INVALID_PARAMETER;
1650 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
1651 rc = ACTION_PerformUIAction(package, szFirstRun);
1652 msiobj_release( &package->hdr );
1654 MsiCloseHandle(handle);
1656 return rc;
1659 UINT WINAPI MsiCollectUserInfoA(LPCSTR szProduct)
1661 MSIHANDLE handle;
1662 UINT rc;
1663 MSIPACKAGE *package;
1664 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
1666 TRACE("(%s)\n",debugstr_a(szProduct));
1668 rc = MsiOpenProductA(szProduct,&handle);
1669 if (rc != ERROR_SUCCESS)
1670 return ERROR_INVALID_PARAMETER;
1672 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
1673 rc = ACTION_PerformUIAction(package, szFirstRun);
1674 msiobj_release( &package->hdr );
1676 MsiCloseHandle(handle);
1678 return rc;
1681 /***********************************************************************
1682 * MsiConfigureFeatureA [MSI.@]
1684 UINT WINAPI MsiConfigureFeatureA(LPCSTR szProduct, LPCSTR szFeature, INSTALLSTATE eInstallState)
1686 FIXME("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature), eInstallState);
1687 return ERROR_SUCCESS;
1690 /***********************************************************************
1691 * MsiConfigureFeatureW [MSI.@]
1693 UINT WINAPI MsiConfigureFeatureW(LPCWSTR szProduct, LPCWSTR szFeature, INSTALLSTATE eInstallState)
1695 FIXME("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature), eInstallState);
1696 return ERROR_SUCCESS;
1699 UINT WINAPI MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved)
1701 WCHAR path[MAX_PATH];
1703 if(dwReserved) {
1704 FIXME("Don't know how to handle argument %ld\n", dwReserved);
1705 return ERROR_CALL_NOT_IMPLEMENTED;
1708 if(!GetWindowsDirectoryW(path, MAX_PATH)) {
1709 FIXME("GetWindowsDirectory failed unexpected! Error %ld\n",
1710 GetLastError());
1711 return ERROR_CALL_NOT_IMPLEMENTED;
1714 strcatW(path, installerW);
1716 CreateDirectoryW(path, NULL);
1718 return 0;
1721 UINT WINAPI MsiGetShortcutTargetA( LPCSTR szShortcutTarget,
1722 LPSTR szProductCode, LPSTR szFeatureId,
1723 LPSTR szComponentCode )
1725 LPWSTR target;
1726 const int len = MAX_FEATURE_CHARS+1;
1727 WCHAR product[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1], component[MAX_FEATURE_CHARS+1];
1728 UINT r;
1730 target = strdupAtoW( szShortcutTarget );
1731 if (szShortcutTarget && !target )
1732 return ERROR_OUTOFMEMORY;
1733 product[0] = 0;
1734 feature[0] = 0;
1735 component[0] = 0;
1736 r = MsiGetShortcutTargetW( target, product, feature, component );
1737 msi_free( target );
1738 if (r == ERROR_SUCCESS)
1740 WideCharToMultiByte( CP_ACP, 0, product, -1, szProductCode, len, NULL, NULL );
1741 WideCharToMultiByte( CP_ACP, 0, feature, -1, szFeatureId, len, NULL, NULL );
1742 WideCharToMultiByte( CP_ACP, 0, component, -1, szComponentCode, len, NULL, NULL );
1744 return r;
1747 UINT WINAPI MsiGetShortcutTargetW( LPCWSTR szShortcutTarget,
1748 LPWSTR szProductCode, LPWSTR szFeatureId,
1749 LPWSTR szComponentCode )
1751 FIXME("%s\n", debugstr_w(szShortcutTarget));
1752 return ERROR_CALL_NOT_IMPLEMENTED;
1755 UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature,
1756 DWORD dwReinstallMode )
1758 MSIPACKAGE* package = NULL;
1759 UINT r;
1760 DWORD sz;
1761 WCHAR sourcepath[MAX_PATH];
1762 WCHAR filename[MAX_PATH];
1763 static const WCHAR szInstalled[] = {
1764 ' ','L','O','G','V','E','R','B','O','S','E','=','1',' ','I','n','s','t','a','l','l','e','d','=','1',0};
1765 static const WCHAR fmt[] = {'R','E','I','N','S','T','A','L','L','=','%','s',0};
1766 static const WCHAR REINSTALLMODE[] = {'R','E','I','N','S','T','A','L','L','M','O','D','E',0};
1767 WCHAR reinstallmode[11];
1768 LPWSTR ptr;
1769 LPWSTR commandline;
1771 FIXME("%s %s %li\n", debugstr_w(szProduct), debugstr_w(szFeature),
1772 dwReinstallMode);
1774 memset(reinstallmode,0,sizeof(reinstallmode));
1775 ptr = reinstallmode;
1777 if (dwReinstallMode & REINSTALLMODE_FILEMISSING)
1778 { *ptr = 'p'; ptr++; }
1779 if (dwReinstallMode & REINSTALLMODE_FILEOLDERVERSION)
1780 { *ptr = 'o'; ptr++; }
1781 if (dwReinstallMode & REINSTALLMODE_FILEEQUALVERSION)
1782 { *ptr = 'w'; ptr++; }
1783 if (dwReinstallMode & REINSTALLMODE_FILEEXACT)
1784 { *ptr = 'd'; ptr++; }
1785 if (dwReinstallMode & REINSTALLMODE_FILEVERIFY)
1786 { *ptr = 'c'; ptr++; }
1787 if (dwReinstallMode & REINSTALLMODE_FILEREPLACE)
1788 { *ptr = 'a'; ptr++; }
1789 if (dwReinstallMode & REINSTALLMODE_USERDATA)
1790 { *ptr = 'u'; ptr++; }
1791 if (dwReinstallMode & REINSTALLMODE_MACHINEDATA)
1792 { *ptr = 'm'; ptr++; }
1793 if (dwReinstallMode & REINSTALLMODE_SHORTCUT)
1794 { *ptr = 's'; ptr++; }
1795 if (dwReinstallMode & REINSTALLMODE_PACKAGE)
1796 { *ptr = 'v'; ptr++; }
1798 sz = sizeof(sourcepath);
1799 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
1800 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath,
1801 &sz);
1803 sz = sizeof(filename);
1804 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
1805 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
1807 strcatW(sourcepath,filename);
1809 if (dwReinstallMode & REINSTALLMODE_PACKAGE)
1810 r = MSI_OpenPackageW( sourcepath, &package );
1811 else
1812 r = MSI_OpenProductW( szProduct, &package );
1814 if (r != ERROR_SUCCESS)
1815 return r;
1817 MSI_SetPropertyW(package,REINSTALLMODE,reinstallmode);
1819 sz = lstrlenW(szInstalled);
1820 sz += lstrlenW(fmt);
1821 sz += lstrlenW(szFeature);
1823 commandline = msi_alloc(sz * sizeof(WCHAR));
1825 sprintfW(commandline,fmt,szFeature);
1826 lstrcatW(commandline,szInstalled);
1828 r = MSI_InstallPackage( package, sourcepath, commandline );
1830 msiobj_release( &package->hdr );
1832 msi_free(commandline);
1834 return r;
1837 UINT WINAPI MsiReinstallFeatureA( LPCSTR szProduct, LPCSTR szFeature,
1838 DWORD dwReinstallMode )
1840 LPWSTR wszProduct;
1841 LPWSTR wszFeature;
1842 UINT rc;
1844 TRACE("%s %s %li\n", debugstr_a(szProduct), debugstr_a(szFeature),
1845 dwReinstallMode);
1847 wszProduct = strdupAtoW(szProduct);
1848 wszFeature = strdupAtoW(szFeature);
1850 rc = MsiReinstallFeatureW(wszProduct, wszFeature, dwReinstallMode);
1852 msi_free(wszProduct);
1853 msi_free(wszFeature);
1854 return rc;
1857 /***********************************************************************
1858 * MsiEnumPatchesA [MSI.@]
1860 UINT WINAPI MsiEnumPatchesA( LPCSTR szProduct, DWORD iPatchIndex,
1861 LPSTR lpPatchBuf, LPSTR lpTransformsBuf, DWORD* pcchTransformsBuf)
1863 FIXME("%s %ld %p %p %p\n", debugstr_a(szProduct),
1864 iPatchIndex, lpPatchBuf, lpTransformsBuf, pcchTransformsBuf);
1865 return ERROR_NO_MORE_ITEMS;
1868 /***********************************************************************
1869 * MsiEnumPatchesW [MSI.@]
1871 UINT WINAPI MsiEnumPatchesW( LPCWSTR szProduct, DWORD iPatchIndex,
1872 LPWSTR lpPatchBuf, LPWSTR lpTransformsBuf, DWORD* pcchTransformsBuf)
1874 FIXME("%s %ld %p %p %p\n", debugstr_w(szProduct),
1875 iPatchIndex, lpPatchBuf, lpTransformsBuf, pcchTransformsBuf);
1876 return ERROR_NO_MORE_ITEMS;