Commit 072c5e56 authored by Aric Stewart's avatar Aric Stewart Committed by Alexandre Julliard

Implement Publish Components in order for MsiGetQualifiedComponent

apis to work. Also implement MsiGetQualifiedComponent, or at least some of the functionality as it is supposed to install stuff if it is absent, which it does not do yet.
parent 6c303a9c
......@@ -99,6 +99,7 @@ static UINT ACTION_ForceReboot(MSIPACKAGE *package);
static UINT ACTION_ResolveSource(MSIPACKAGE *package);
static UINT ACTION_ExecuteAction(MSIPACKAGE *package);
static UINT ACTION_RegisterFonts(MSIPACKAGE *package);
static UINT ACTION_PublishComponents(MSIPACKAGE *package);
/*
......@@ -324,7 +325,7 @@ static struct _actions StandardActions[] = {
{ szInstallServices, NULL},
{ szPatchFiles, NULL},
{ szProcessComponents, ACTION_ProcessComponents },
{ szPublishComponents, NULL},
{ szPublishComponents, ACTION_PublishComponents },
{ szPublishFeatures, ACTION_PublishFeatures },
{ szPublishProduct, ACTION_PublishProduct },
{ szRegisterClassInfo, ACTION_RegisterClassInfo },
......@@ -6292,6 +6293,114 @@ static UINT ACTION_RegisterFonts(MSIPACKAGE *package)
return rc;
}
static UINT ITERATE_PublishComponent(MSIRECORD *rec, LPVOID param)
{
MSIPACKAGE *package = (MSIPACKAGE*)param;
LPWSTR productid=NULL, compgroupid=NULL;
LPWSTR feature=NULL;
LPWSTR text = NULL;
LPWSTR qualifier = NULL;
LPWSTR component = NULL;
GUID clsid;
WCHAR productid_85[21];
WCHAR component_85[21];
HKEY hkey;
UINT rc = ERROR_SUCCESS;
UINT index;
/*
* I have a fair bit of confusion as to when a < is used and when a > is
* used. I do not think i have it right...
*/
static WCHAR fmt1[] = {'%','s','%','s','<','%','s',0,0};
static WCHAR fmt2[] = {'%','s','%','s','>',0,0};
LPWSTR output = NULL;
DWORD sz = 0;
memset(productid_85,0,sizeof(productid_85));
memset(component_85,0,sizeof(component_85));
compgroupid = load_dynamic_stringW(rec,1);
rc = MSIREG_OpenUserComponentsKey(compgroupid, &hkey, TRUE);
if (rc != ERROR_SUCCESS)
goto end;
productid = load_dynamic_property(package,szProductCode,NULL);
CLSIDFromString(productid, &clsid);
encode_base85_guid(&clsid,productid_85);
text = load_dynamic_stringW(rec,4);
qualifier = load_dynamic_stringW(rec,2);
feature = load_dynamic_stringW(rec,5);
component = load_dynamic_stringW(rec,3);
index = get_loaded_component(package, component);
CLSIDFromString(package->components[index].ComponentId, &clsid);
encode_base85_guid(&clsid,component_85);
TRACE("Doing something with this... %s = %s %s %s %s\n",
debugstr_w(qualifier), debugstr_w(productid_85),
debugstr_w(feature), debugstr_w(text), debugstr_w(component_85));
sz = lstrlenW(productid_85) + lstrlenW(feature);
if (text)
sz += lstrlenW(text);
if (component && index >= 0)
sz += lstrlenW(component_85);
sz+=3;
sz *= sizeof(WCHAR);
output = HeapAlloc(GetProcessHeap(),0,sz);
memset(output,0,sz);
if (ACTION_VerifyComponentForAction(package, index, INSTALLSTATE_LOCAL))
sprintfW(output,fmt1,productid_85,feature,component_85);
else
sprintfW(output,fmt2,productid_85,feature);
if (text)
strcatW(output,text);
sz = (lstrlenW(output)+2) * sizeof(WCHAR);
RegSetValueExW(hkey, qualifier,0,REG_MULTI_SZ, (LPBYTE)output, sz);
end:
RegCloseKey(hkey);
HeapFree(GetProcessHeap(),0,output);
HeapFree(GetProcessHeap(),0,compgroupid);
HeapFree(GetProcessHeap(),0,component);
HeapFree(GetProcessHeap(),0,productid);
HeapFree(GetProcessHeap(),0,feature);
HeapFree(GetProcessHeap(),0,text);
HeapFree(GetProcessHeap(),0,qualifier);
return rc;
}
/*
* At present I am ignorning the advertised components part of this and only
* focusing on the qualified component sets
*/
static UINT ACTION_PublishComponents(MSIPACKAGE *package)
{
UINT rc;
MSIQUERY * view;
static const WCHAR ExecSeqQuery[] =
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
'P','u','b','l','i','s','h','C','o','m','p','o','n','e','n','t',0};
rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
if (rc != ERROR_SUCCESS)
return ERROR_SUCCESS;
rc = MSI_IterateRecords(view, NULL, ITERATE_PublishComponent, package);
msiobj_release(&view->hdr);
return rc;
}
/* Msi functions that seem appropriate here */
UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
{
......
......@@ -35,6 +35,7 @@
#include "wincrypt.h"
#include "winver.h"
#include "winuser.h"
#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi);
......@@ -1297,11 +1298,107 @@ UINT WINAPI MsiProvideQualifiedComponentExW(LPCWSTR szComponent,
DWORD Unused1, DWORD Unused2, LPWSTR lpPathBuf,
DWORD* pcchPathBuf)
{
FIXME("%s %s %li %s %li %li %p %p\n", debugstr_w(szComponent),
HKEY hkey;
UINT rc;
LPWSTR info;
DWORD sz;
LPWSTR product = NULL;
LPWSTR component = NULL;
LPWSTR ptr;
GUID clsid;
TRACE("%s %s %li %s %li %li %p %p\n", debugstr_w(szComponent),
debugstr_w(szQualifier), dwInstallMode, debugstr_w(szProduct),
Unused1, Unused2, lpPathBuf, pcchPathBuf);
rc = MSIREG_OpenUserComponentsKey(szComponent, &hkey, FALSE);
if (rc != ERROR_SUCCESS)
return ERROR_INDEX_ABSENT;
sz = 0;
rc = RegQueryValueExW( hkey, szQualifier, NULL, NULL, NULL, &sz);
if (sz <= 0)
{
RegCloseKey(hkey);
return ERROR_INDEX_ABSENT;
}
info = HeapAlloc(GetProcessHeap(),0,sz);
rc = RegQueryValueExW( hkey, szQualifier, NULL, NULL, (LPBYTE)info, &sz);
if (rc != ERROR_SUCCESS)
{
RegCloseKey(hkey);
HeapFree(GetProcessHeap(),0,info);
return ERROR_INDEX_ABSENT;
}
/* find the component */
ptr = strchrW(&info[20],'<');
if (ptr)
ptr++;
else
{
RegCloseKey(hkey);
HeapFree(GetProcessHeap(),0,info);
return ERROR_INDEX_ABSENT;
}
return ERROR_INDEX_ABSENT;
if (!szProduct)
{
decode_base85_guid(info,&clsid);
StringFromCLSID(&clsid, &product);
}
decode_base85_guid(ptr,&clsid);
StringFromCLSID(&clsid, &component);
if (!szProduct)
rc = MsiGetComponentPathW(product, component, lpPathBuf, pcchPathBuf);
else
rc = MsiGetComponentPathW(szProduct, component, lpPathBuf, pcchPathBuf);
RegCloseKey(hkey);
HeapFree(GetProcessHeap(),0,info);
HeapFree(GetProcessHeap(),0,product);
HeapFree(GetProcessHeap(),0,component);
return rc;
}
UINT WINAPI MsiProvideQualifiedComponentW( LPCWSTR szComponent,
LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR lpPathBuf,
DWORD* pcchPathBuf)
{
return MsiProvideQualifiedComponentExW(szComponent, szQualifier,
dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
}
UINT WINAPI MsiProvideQualifiedComponentA( LPCSTR szComponent,
LPCSTR szQualifier, DWORD dwInstallMode, LPSTR lpPathBuf,
DWORD* pcchPathBuf)
{
LPWSTR szwComponent, szwQualifier, lpwPathBuf;
DWORD pcchwPathBuf;
UINT rc;
TRACE("%s %s %li %p %p\n",szComponent, szQualifier,
dwInstallMode, lpPathBuf, pcchPathBuf);
szwComponent= strdupAtoW( szComponent);
szwQualifier= strdupAtoW( szQualifier);
lpwPathBuf = HeapAlloc(GetProcessHeap(),0,*pcchPathBuf * sizeof(WCHAR));
pcchwPathBuf = *pcchPathBuf;
rc = MsiProvideQualifiedComponentW(szwComponent, szwQualifier,
dwInstallMode, lpwPathBuf, &pcchwPathBuf);
HeapFree(GetProcessHeap(),0,szwComponent);
HeapFree(GetProcessHeap(),0,szwQualifier);
*pcchPathBuf = WideCharToMultiByte(CP_ACP, 0, lpwPathBuf, pcchwPathBuf,
lpPathBuf, *pcchPathBuf, NULL, NULL);
HeapFree(GetProcessHeap(),0,lpwPathBuf);
return rc;
}
USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct, LPWSTR lpUserNameBuf,
......
......@@ -105,8 +105,8 @@
105 stdcall MsiProvideComponentFromDescriptorA(str ptr ptr ptr)
106 stdcall MsiProvideComponentFromDescriptorW(wstr ptr ptr ptr)
107 stub MsiProvideComponentW
108 stub MsiProvideQualifiedComponentA
109 stub MsiProvideQualifiedComponentW
108 stdcall MsiProvideQualifiedComponentA(str str long ptr ptr)
109 stdcall MsiProvideQualifiedComponentW(str str long ptr ptr)
110 stdcall MsiQueryFeatureStateA(str str)
111 stdcall MsiQueryFeatureStateW(wstr wstr)
112 stdcall MsiQueryProductStateA(str)
......
......@@ -357,6 +357,7 @@ extern UINT MSIREG_OpenUserProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create
extern UINT MSIREG_OpenFeatures(HKEY* key);
extern UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create);
extern UINT MSIREG_OpenComponents(HKEY* key);
extern UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create);
extern UINT MSIREG_OpenComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create);
extern UINT MSIREG_OpenProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create);
extern UINT MSIREG_OpenUserFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create);
......
......@@ -85,6 +85,13 @@ static const WCHAR szInstaller_Components_fmt[] = {
'C','o','m','p','o','n','e','n','t','s','\\',
'%','s',0};
static const WCHAR szUser_Components_fmt[] = {
'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\',
'I','n','s','t','a','l','l','e','r','\\',
'C','o','m','p','o','n','e','n','t','s','\\',
'%','s',0};
static const WCHAR szUninstall_fmt[] = {
'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\',
......@@ -388,6 +395,26 @@ UINT MSIREG_OpenComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create)
return rc;
}
UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create)
{
UINT rc;
WCHAR squished_cc[GUID_SIZE];
WCHAR keypath[0x200];
TRACE("%s\n",debugstr_w(szComponent));
squash_guid(szComponent,squished_cc);
TRACE("squished (%s)\n", debugstr_w(squished_cc));
sprintfW(keypath,szUser_Components_fmt,squished_cc);
if (create)
rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
else
rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
return rc;
}
UINT MSIREG_OpenProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create)
{
UINT rc;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment