From 072c5e56a2973685c4393694e2f6bcd02f006425 Mon Sep 17 00:00:00 2001 From: Aric Stewart Date: Wed, 20 Apr 2005 12:50:05 +0000 Subject: [PATCH] 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. --- dlls/msi/action.c | 111 +++++++++++++++++++++++++++++++++++++++++++- dlls/msi/msi.c | 101 +++++++++++++++++++++++++++++++++++++++- dlls/msi/msi.spec | 4 +- dlls/msi/msipriv.h | 1 + dlls/msi/registry.c | 27 +++++++++++ 5 files changed, 239 insertions(+), 5 deletions(-) diff --git a/dlls/msi/action.c b/dlls/msi/action.c index 99b9f4cb215..c821ae4fe27 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -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 ) { diff --git a/dlls/msi/msi.c b/dlls/msi/msi.c index aee845f4a63..37961137efb 100644 --- a/dlls/msi/msi.c +++ b/dlls/msi/msi.c @@ -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; - 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; + } + + 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, diff --git a/dlls/msi/msi.spec b/dlls/msi/msi.spec index b15557f89fa..600f3538a9e 100644 --- a/dlls/msi/msi.spec +++ b/dlls/msi/msi.spec @@ -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) diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index ba4688ba02f..8c3d4df9a74 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -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); diff --git a/dlls/msi/registry.c b/dlls/msi/registry.c index c6de5692a96..164337e7e2d 100644 --- a/dlls/msi/registry.c +++ b/dlls/msi/registry.c @@ -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;