From 2b8bf597b5f4f992c977f26871d0aa131734de43 Mon Sep 17 00:00:00 2001 From: Aric Stewart Date: Thu, 28 Apr 2005 18:28:11 +0000 Subject: [PATCH] Correct user component publication. Implement MsiEnumComponentQualifiers. --- dlls/msi/action.c | 13 +++-- dlls/msi/msi.c | 2 +- dlls/msi/registry.c | 124 ++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 129 insertions(+), 10 deletions(-) diff --git a/dlls/msi/action.c b/dlls/msi/action.c index 74927ba7f04..5825b6ba7cb 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -6310,9 +6310,12 @@ static UINT ITERATE_PublishComponent(MSIRECORD *rec, LPVOID param) /* * 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... + * + * Ok it appears that the > is used if there is a guid for the compoenent + * and the < is used if not. */ - static WCHAR fmt1[] = {'%','s','%','s','<','%','s',0,0}; - static WCHAR fmt2[] = {'%','s','%','s','>',0,0}; + static WCHAR fmt1[] = {'%','s','%','s','<',0,0}; + static WCHAR fmt2[] = {'%','s','%','s','>','%','s',0,0}; LPWSTR output = NULL; DWORD sz = 0; @@ -6355,10 +6358,10 @@ static UINT ITERATE_PublishComponent(MSIRECORD *rec, LPVOID param) output = HeapAlloc(GetProcessHeap(),0,sz); memset(output,0,sz); - if (ACTION_VerifyComponentForAction(package, index, INSTALLSTATE_LOCAL)) - sprintfW(output,fmt1,productid_85,feature,component_85); + if (component && index >= 0) + sprintfW(output,fmt2,productid_85,feature,component_85); else - sprintfW(output,fmt2,productid_85,feature); + sprintfW(output,fmt1,productid_85,feature); if (text) strcatW(output,text); diff --git a/dlls/msi/msi.c b/dlls/msi/msi.c index a0f67146ff5..9f8905e9933 100644 --- a/dlls/msi/msi.c +++ b/dlls/msi/msi.c @@ -1425,7 +1425,7 @@ UINT WINAPI MsiProvideQualifiedComponentExW(LPCWSTR szComponent, } /* find the component */ - ptr = strchrW(&info[20],'<'); + ptr = strchrW(&info[20],'>'); if (ptr) ptr++; else diff --git a/dlls/msi/registry.c b/dlls/msi/registry.c index 164337e7e2d..61d8b1db73a 100644 --- a/dlls/msi/registry.c +++ b/dlls/msi/registry.c @@ -726,20 +726,136 @@ UINT WINAPI MsiEnumComponentQualifiersA( LPSTR szComponent, DWORD iIndex, LPSTR lpQualifierBuf, DWORD* pcchQualifierBuf, LPSTR lpApplicationDataBuf, DWORD* pcchApplicationDataBuf) { - FIXME("%s %08lx %p %p %p %p\n", debugstr_a(szComponent), iIndex, + LPWSTR szwComponent; + LPWSTR lpwQualifierBuf; + DWORD pcchwQualifierBuf; + LPWSTR lpwApplicationDataBuf; + DWORD pcchwApplicationDataBuf; + DWORD rc; + DWORD length; + + TRACE("%s %08lx %p %p %p %p\n", debugstr_a(szComponent), iIndex, lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf, pcchApplicationDataBuf); - return ERROR_CALL_NOT_IMPLEMENTED; + + szwComponent = strdupAtoW(szComponent); + + if (lpQualifierBuf) + lpwQualifierBuf = HeapAlloc(GetProcessHeap(),0, (*pcchQualifierBuf) * + sizeof(WCHAR)); + else + lpwQualifierBuf = NULL; + + if (pcchQualifierBuf) + pcchwQualifierBuf = *pcchQualifierBuf; + else + pcchwQualifierBuf = 0; + + if (lpApplicationDataBuf) + lpwApplicationDataBuf = HeapAlloc(GetProcessHeap(),0 , + (*pcchApplicationDataBuf) * sizeof(WCHAR)); + else + lpwApplicationDataBuf = NULL; + + if (pcchApplicationDataBuf) + pcchwApplicationDataBuf = *pcchApplicationDataBuf; + else + pcchwApplicationDataBuf = 0; + + rc = MsiEnumComponentQualifiersW( szwComponent, iIndex, lpwQualifierBuf, + &pcchwQualifierBuf, lpwApplicationDataBuf, + &pcchwApplicationDataBuf); + + /* + * A bit of wizardry to report back the length without the null. + * just in case the buffer is to small and is filled. + */ + if (lpQualifierBuf) + { + length = WideCharToMultiByte(CP_ACP, 0, lpwQualifierBuf, -1, + lpQualifierBuf, *pcchQualifierBuf, NULL, NULL); + + if (*pcchQualifierBuf == length && lpQualifierBuf[length-1]) + *pcchQualifierBuf = length; + else + *pcchQualifierBuf = length - 1; + } + if (lpApplicationDataBuf) + { + length = WideCharToMultiByte(CP_ACP, 0, + lpwApplicationDataBuf, -1, lpApplicationDataBuf, + *pcchApplicationDataBuf, NULL, NULL); + + if (*pcchApplicationDataBuf == length && lpApplicationDataBuf[length-1]) + *pcchApplicationDataBuf = length; + else + *pcchApplicationDataBuf = length - 1; + } + + HeapFree(GetProcessHeap(),0,lpwApplicationDataBuf); + HeapFree(GetProcessHeap(),0,lpwQualifierBuf); + HeapFree(GetProcessHeap(),0,szwComponent); + + return rc; } UINT WINAPI MsiEnumComponentQualifiersW( LPWSTR szComponent, DWORD iIndex, LPWSTR lpQualifierBuf, DWORD* pcchQualifierBuf, LPWSTR lpApplicationDataBuf, DWORD* pcchApplicationDataBuf ) { - FIXME("%s %08lx %p %p %p %p\n", debugstr_w(szComponent), iIndex, + UINT rc; + HKEY key; + DWORD actual_pcchQualifierBuf = 0; + DWORD actual_pcchApplicationDataBuf = 0; + LPWSTR full_buffer = NULL; + DWORD full_buffer_size = 0; + LPWSTR ptr; + + TRACE("%s %08lx %p %p %p %p\n", debugstr_w(szComponent), iIndex, lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf, pcchApplicationDataBuf); - return ERROR_CALL_NOT_IMPLEMENTED; + + if (pcchQualifierBuf) + actual_pcchQualifierBuf = *pcchQualifierBuf * sizeof(WCHAR); + if (pcchApplicationDataBuf) + actual_pcchApplicationDataBuf = *pcchApplicationDataBuf * sizeof(WCHAR); + + rc = MSIREG_OpenUserComponentsKey(szComponent, &key, FALSE); + if (rc != ERROR_SUCCESS) + return ERROR_UNKNOWN_COMPONENT; + + full_buffer_size = (52 * sizeof(WCHAR)) + actual_pcchApplicationDataBuf; + full_buffer = HeapAlloc(GetProcessHeap(),0,full_buffer_size); + + rc = RegEnumValueW(key, iIndex, lpQualifierBuf, pcchQualifierBuf, NULL, + NULL, (LPBYTE)full_buffer, &full_buffer_size); + + RegCloseKey(key); + + if (rc == ERROR_SUCCESS || rc == ERROR_MORE_DATA) + { + if (lpApplicationDataBuf && pcchApplicationDataBuf) + { + ptr = full_buffer; + /* Skip the first guid */ + ptr += 21; + + /* Skip the name and the component guid if it exists */ + if (strchrW(ptr,'<')) + ptr = strchrW(ptr,'<'); + else + ptr = strchrW(ptr,'>') + 21; + + lstrcpynW(lpApplicationDataBuf,ptr,*pcchApplicationDataBuf); + *pcchApplicationDataBuf = strlenW(ptr); + } + if (lpQualifierBuf && pcchQualifierBuf) + *pcchQualifierBuf /= sizeof(WCHAR); + TRACE("Providing %s and %s\n", debugstr_w(lpQualifierBuf), + debugstr_w(lpApplicationDataBuf)); + } + + return rc; } UINT WINAPI MsiEnumRelatedProductsW(LPCWSTR szUpgradeCode, DWORD dwReserved,