msi: Implement MsiEnumPatchesExW.

This commit is contained in:
James Hawkins 2008-12-08 03:14:21 -06:00 committed by Alexandre Julliard
parent a32fcfa9b1
commit 87fef9fd22
1 changed files with 309 additions and 3 deletions

View File

@ -168,6 +168,15 @@ static const WCHAR szUserDataProd_fmt[] = {
'U','s','e','r','D','a','t','a','\\', 'U','s','e','r','D','a','t','a','\\',
'%','s','\\','P','r','o','d','u','c','t','s','\\','%','s',0}; '%','s','\\','P','r','o','d','u','c','t','s','\\','%','s',0};
static const WCHAR szUserDataPatch_fmt[] = {
'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\',
'W','i','n','d','o','w','s','\\',
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
'I','n','s','t','a','l','l','e','r','\\',
'U','s','e','r','D','a','t','a','\\',
'%','s','\\','P','a','t','c','h','e','s','\\','%','s',0};
static const WCHAR szInstallProperties_fmt[] = { static const WCHAR szInstallProperties_fmt[] = {
'S','o','f','t','w','a','r','e','\\', 'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\', 'M','i','c','r','o','s','o','f','t','\\',
@ -241,6 +250,9 @@ BOOL unsquash_guid(LPCWSTR in, LPWSTR out)
{ {
DWORD i,n=0; DWORD i,n=0;
if (lstrlenW(in) != 32)
return FALSE;
out[n++]='{'; out[n++]='{';
for(i=0; i<8; i++) for(i=0; i<8; i++)
out[n++] = in[7-i]; out[n++] = in[7-i];
@ -860,6 +872,32 @@ UINT MSIREG_OpenUserDataProductKey(LPCWSTR szProduct, HKEY *key, BOOL create)
return rc; return rc;
} }
UINT MSIREG_OpenUserDataPatchKey(LPWSTR patch, HKEY *key, BOOL create)
{
UINT rc;
WCHAR keypath[0x200];
LPWSTR usersid;
TRACE("\n");
rc = get_user_sid(&usersid);
if (rc != ERROR_SUCCESS || !usersid)
{
ERR("Failed to retrieve user SID: %d\n", rc);
return rc;
}
sprintfW(keypath, szUserDataPatch_fmt, usersid, patch);
if (create)
rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
else
rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
LocalFree(usersid);
return rc;
}
UINT MSIREG_OpenLocalUserDataProductKey(LPCWSTR szProduct, HKEY *key, BOOL create) UINT MSIREG_OpenLocalUserDataProductKey(LPCWSTR szProduct, HKEY *key, BOOL create)
{ {
WCHAR squished_pc[GUID_SIZE]; WCHAR squished_pc[GUID_SIZE];
@ -1727,19 +1765,287 @@ done:
return r; return r;
} }
static UINT msi_get_patch_state(LPCWSTR prodcode, LPCWSTR usersid,
LPWSTR patch, MSIPATCHSTATE *state)
{
DWORD type, val, size;
HKEY prod, hkey = 0;
HKEY udpatch = 0;
LONG res;
UINT r = ERROR_NO_MORE_ITEMS;
static const WCHAR szPatches[] = {'P','a','t','c','h','e','s',0};
static const WCHAR szState[] = {'S','t','a','t','e',0};
/* FIXME: usersid might not be current user */
r = MSIREG_OpenUserDataProductKey(prodcode, &prod, FALSE);
if (r != ERROR_SUCCESS)
return ERROR_NO_MORE_ITEMS;
res = RegOpenKeyExW(prod, szPatches, 0, KEY_READ, &hkey);
if (res != ERROR_SUCCESS)
goto done;
res = RegOpenKeyExW(hkey, patch, 0, KEY_READ, &udpatch);
if (res != ERROR_SUCCESS)
goto done;
size = sizeof(DWORD);
res = RegGetValueW(udpatch, NULL, szState, RRF_RT_DWORD, &type, &val, &size);
if (res != ERROR_SUCCESS ||
val < MSIPATCHSTATE_APPLIED || val > MSIPATCHSTATE_REGISTERED)
{
r = ERROR_BAD_CONFIGURATION;
goto done;
}
*state = val;
r = ERROR_SUCCESS;
done:
RegCloseKey(udpatch);
RegCloseKey(hkey);
RegCloseKey(prod);
return r;
}
static UINT msi_check_product_patches(LPCWSTR prodcode, LPCWSTR usersid,
MSIINSTALLCONTEXT context, DWORD filter, DWORD index, DWORD *idx,
LPWSTR patch, LPWSTR targetprod, MSIINSTALLCONTEXT *targetctx,
LPWSTR targetsid, DWORD *sidsize)
{
MSIPATCHSTATE state;
LPWSTR ptr, patches = NULL;
HKEY prod, patchkey = 0;
HKEY localprod = 0, localpatch = 0;
DWORD type, size;
LONG res;
UINT temp, r = ERROR_NO_MORE_ITEMS;
static const WCHAR szPatches[] = {'P','a','t','c','h','e','s',0};
static const WCHAR szState[] = {'S','t','a','t','e',0};
static const WCHAR szEmpty[] = {0};
if (MSIREG_OpenProductKey(prodcode, context, &prod, FALSE) != ERROR_SUCCESS)
return ERROR_NO_MORE_ITEMS;
size = 0;
res = RegGetValueW(prod, szPatches, szPatches, RRF_RT_ANY, &type, NULL,
&size);
if (res != ERROR_SUCCESS)
goto done;
if (type != REG_MULTI_SZ)
{
r = ERROR_BAD_CONFIGURATION;
goto done;
}
patches = msi_alloc(size);
if (!patches)
{
r = ERROR_OUTOFMEMORY;
goto done;
}
res = RegGetValueW(prod, szPatches, szPatches, RRF_RT_ANY, &type,
patches, &size);
if (res != ERROR_SUCCESS)
goto done;
ptr = patches;
for (ptr = patches; *ptr && r == ERROR_NO_MORE_ITEMS; ptr += lstrlenW(ptr))
{
if (!unsquash_guid(ptr, patch))
{
r = ERROR_BAD_CONFIGURATION;
goto done;
}
size = 0;
res = RegGetValueW(prod, szPatches, ptr, RRF_RT_REG_SZ,
&type, NULL, &size);
if (res != ERROR_SUCCESS)
continue;
if (context == MSIINSTALLCONTEXT_USERMANAGED)
{
if (!(filter & MSIPATCHSTATE_APPLIED))
{
temp = msi_get_patch_state(prodcode, usersid, ptr, &state);
if (temp == ERROR_BAD_CONFIGURATION)
{
r = ERROR_BAD_CONFIGURATION;
goto done;
}
if (temp != ERROR_SUCCESS || !(filter & state))
continue;
}
}
else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
{
if (!(filter & MSIPATCHSTATE_APPLIED))
{
temp = msi_get_patch_state(prodcode, usersid, ptr, &state);
if (temp == ERROR_BAD_CONFIGURATION)
{
r = ERROR_BAD_CONFIGURATION;
goto done;
}
if (temp != ERROR_SUCCESS || !(filter & state))
continue;
}
else
{
temp = MSIREG_OpenUserDataPatchKey(ptr, &patchkey, FALSE);
RegCloseKey(patchkey);
if (temp != ERROR_SUCCESS)
continue;
}
}
else if (context == MSIINSTALLCONTEXT_MACHINE)
{
usersid = szEmpty;
if (MSIREG_OpenLocalUserDataProductKey(prodcode, &localprod, FALSE) == ERROR_SUCCESS &&
RegOpenKeyExW(localprod, szPatches, 0, KEY_READ, &localpatch) == ERROR_SUCCESS &&
RegOpenKeyExW(localpatch, ptr, 0, KEY_READ, &patchkey) == ERROR_SUCCESS)
{
res = RegGetValueW(patchkey, NULL, szState, RRF_RT_REG_DWORD,
&type, &state, &size);
if (!(filter & state))
res = ERROR_NO_MORE_ITEMS;
RegCloseKey(patchkey);
}
RegCloseKey(localpatch);
RegCloseKey(localprod);
if (res != ERROR_SUCCESS)
continue;
}
if (*idx < index)
{
(*idx)++;
continue;
}
r = ERROR_SUCCESS;
lstrcpyW(targetprod, prodcode);
if (targetctx)
*targetctx = context;
if (targetsid)
{
lstrcpynW(targetsid, usersid, *sidsize);
if (lstrlenW(usersid) >= *sidsize)
r = ERROR_MORE_DATA;
}
if (sidsize)
{
*sidsize = lstrlenW(usersid);
if (!targetsid)
*sidsize *= sizeof(WCHAR);
}
}
done:
RegCloseKey(prod);
msi_free(patches);
return r;
}
/*********************************************************************** /***********************************************************************
* MsiEnumPatchesW [MSI.@] * MsiEnumPatchesExW [MSI.@]
*/ */
UINT WINAPI MsiEnumPatchesExW(LPCWSTR szProductCode, LPCWSTR szUserSid, UINT WINAPI MsiEnumPatchesExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
DWORD dwContext, DWORD dwFilter, DWORD dwIndex, LPWSTR szPatchCode, DWORD dwContext, DWORD dwFilter, DWORD dwIndex, LPWSTR szPatchCode,
LPWSTR szTargetProductCode, MSIINSTALLCONTEXT *pdwTargetProductContext, LPWSTR szTargetProductCode, MSIINSTALLCONTEXT *pdwTargetProductContext,
LPWSTR szTargetUserSid, LPDWORD pcchTargetUserSid) LPWSTR szTargetUserSid, LPDWORD pcchTargetUserSid)
{ {
FIXME("(%s, %s, %d, %d, %d, %p, %p, %p, %p, %p) stub!\n", WCHAR squished_pc[GUID_SIZE];
DWORD idx = 0;
UINT r;
static int last_index = 0;
TRACE("(%s, %s, %d, %d, %d, %p, %p, %p, %p, %p)\n",
debugstr_w(szProductCode), debugstr_w(szUserSid), dwContext, dwFilter, debugstr_w(szProductCode), debugstr_w(szUserSid), dwContext, dwFilter,
dwIndex, szPatchCode, szTargetProductCode, pdwTargetProductContext, dwIndex, szPatchCode, szTargetProductCode, pdwTargetProductContext,
szTargetUserSid, pcchTargetUserSid); szTargetUserSid, pcchTargetUserSid);
return ERROR_NO_MORE_ITEMS;
if (!szProductCode || !squash_guid(szProductCode, squished_pc))
return ERROR_INVALID_PARAMETER;
if (!lstrcmpW(szUserSid, localsid))
return ERROR_INVALID_PARAMETER;
if (dwContext & MSIINSTALLCONTEXT_MACHINE && szUserSid)
return ERROR_INVALID_PARAMETER;
if (dwContext <= MSIINSTALLCONTEXT_NONE ||
dwContext > MSIINSTALLCONTEXT_ALL)
return ERROR_INVALID_PARAMETER;
if (dwFilter <= MSIPATCHSTATE_INVALID || dwFilter > MSIPATCHSTATE_ALL)
return ERROR_INVALID_PARAMETER;
if (dwIndex && dwIndex - last_index != 1)
return ERROR_INVALID_PARAMETER;
if (dwIndex == 0)
last_index = 0;
if (dwContext & MSIINSTALLCONTEXT_USERMANAGED)
{
r = msi_check_product_patches(szProductCode, szUserSid,
MSIINSTALLCONTEXT_USERMANAGED, dwFilter,
dwIndex, &idx, szPatchCode,
szTargetProductCode,
pdwTargetProductContext,
szTargetUserSid, pcchTargetUserSid);
if (r != ERROR_NO_MORE_ITEMS)
goto done;
}
if (dwContext & MSIINSTALLCONTEXT_USERUNMANAGED)
{
r = msi_check_product_patches(szProductCode, szUserSid,
MSIINSTALLCONTEXT_USERUNMANAGED, dwFilter,
dwIndex, &idx, szPatchCode,
szTargetProductCode,
pdwTargetProductContext,
szTargetUserSid, pcchTargetUserSid);
if (r != ERROR_NO_MORE_ITEMS)
goto done;
}
if (dwContext & MSIINSTALLCONTEXT_MACHINE)
{
r = msi_check_product_patches(szProductCode, szUserSid,
MSIINSTALLCONTEXT_MACHINE, dwFilter,
dwIndex, &idx, szPatchCode,
szTargetProductCode,
pdwTargetProductContext,
szTargetUserSid, pcchTargetUserSid);
if (r != ERROR_NO_MORE_ITEMS)
goto done;
}
done:
if (r == ERROR_SUCCESS)
last_index = dwIndex;
return r;
} }
/*********************************************************************** /***********************************************************************