From 438ad93b223dc8cb722b1550adca160a59812e0c Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Mon, 15 Feb 2010 16:18:30 +0100 Subject: [PATCH] msi: Implement and test MsiGetPatchInfoA/W. --- dlls/msi/msi.c | 87 +++++++++++++++++++++ dlls/msi/msi.spec | 4 +- dlls/msi/tests/msi.c | 178 +++++++++++++++++++++++++++++++++++++++++++ include/msi.h | 4 + 4 files changed, 271 insertions(+), 2 deletions(-) diff --git a/dlls/msi/msi.c b/dlls/msi/msi.c index 4d9da4cd68f..07356405718 100644 --- a/dlls/msi/msi.c +++ b/dlls/msi/msi.c @@ -1613,6 +1613,93 @@ done: return r; } +UINT WINAPI MsiGetPatchInfoA( LPCSTR patch, LPCSTR attr, LPSTR buffer, LPDWORD buflen ) +{ + UINT r = ERROR_OUTOFMEMORY; + DWORD size; + LPWSTR patchW = NULL, attrW = NULL, bufferW = NULL; + + TRACE("%s %s %p %p\n", debugstr_a(patch), debugstr_a(attr), buffer, buflen); + + if (!patch || !attr) + return ERROR_INVALID_PARAMETER; + + if (!(patchW = strdupAtoW( patch ))) + goto done; + + if (!(attrW = strdupAtoW( attr ))) + goto done; + + size = 0; + r = MsiGetPatchInfoW( patchW, attrW, NULL, &size ); + if (r != ERROR_SUCCESS) + goto done; + + size++; + if (!(bufferW = msi_alloc( size * sizeof(WCHAR) ))) + { + r = ERROR_OUTOFMEMORY; + goto done; + } + + r = MsiGetPatchInfoW( patchW, attrW, bufferW, &size ); + if (r == ERROR_SUCCESS) + { + int len = WideCharToMultiByte( CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL ); + if (len > *buflen) + r = ERROR_MORE_DATA; + else if (buffer) + WideCharToMultiByte( CP_ACP, 0, bufferW, -1, buffer, *buflen, NULL, NULL ); + + *buflen = len - 1; + } + +done: + msi_free( patchW ); + msi_free( attrW ); + msi_free( bufferW ); + return r; +} + +UINT WINAPI MsiGetPatchInfoW( LPCWSTR patch, LPCWSTR attr, LPWSTR buffer, LPDWORD buflen ) +{ + UINT r; + WCHAR product[GUID_SIZE]; + DWORD index; + + TRACE("%s %s %p %p\n", debugstr_w(patch), debugstr_w(attr), buffer, buflen); + + if (!patch || !attr) + return ERROR_INVALID_PARAMETER; + + if (strcmpW( INSTALLPROPERTY_LOCALPACKAGEW, attr )) + return ERROR_UNKNOWN_PROPERTY; + + index = 0; + while (1) + { + r = MsiEnumProductsW( index, product ); + if (r != ERROR_SUCCESS) + break; + + r = MsiGetPatchInfoExW( patch, product, NULL, MSIINSTALLCONTEXT_USERMANAGED, attr, buffer, buflen ); + if (r == ERROR_SUCCESS || r == ERROR_MORE_DATA) + return r; + + r = MsiGetPatchInfoExW( patch, product, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, attr, buffer, buflen ); + if (r == ERROR_SUCCESS || r == ERROR_MORE_DATA) + return r; + + r = MsiGetPatchInfoExW( patch, product, NULL, MSIINSTALLCONTEXT_MACHINE, attr, buffer, buflen ); + if (r == ERROR_SUCCESS || r == ERROR_MORE_DATA) + return r; + + index++; + } + + return ERROR_UNKNOWN_PRODUCT; +} + UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes) { LPWSTR szwLogFile = NULL; diff --git a/dlls/msi/msi.spec b/dlls/msi/msi.spec index 147502811be..30daec931a6 100644 --- a/dlls/msi/msi.spec +++ b/dlls/msi/msi.spec @@ -171,8 +171,8 @@ 175 stdcall MsiApplyPatchW(wstr wstr long wstr) 176 stdcall MsiAdvertiseScriptA(str long ptr long) 177 stdcall MsiAdvertiseScriptW(wstr long ptr long) -178 stub MsiGetPatchInfoA -179 stub MsiGetPatchInfoW +178 stdcall MsiGetPatchInfoA(str str ptr ptr) +179 stdcall MsiGetPatchInfoW(wstr wstr ptr ptr) 180 stdcall MsiEnumPatchesA(str long ptr ptr ptr) 181 stdcall MsiEnumPatchesW(str long ptr ptr ptr) 182 stdcall -private DllGetVersion(ptr) diff --git a/dlls/msi/tests/msi.c b/dlls/msi/tests/msi.c index e3baa09bc3d..2995adbe56b 100644 --- a/dlls/msi/tests/msi.c +++ b/dlls/msi/tests/msi.c @@ -10888,6 +10888,183 @@ static void test_MsiGetPatchInfoEx(void) LocalFree(usersid); } +static void test_MsiGetPatchInfo(void) +{ + UINT r; + char prod_code[MAX_PATH], prod_squashed[MAX_PATH], val[MAX_PATH]; + char patch_code[MAX_PATH], patch_squashed[MAX_PATH], keypath[MAX_PATH]; + WCHAR valW[MAX_PATH], patch_codeW[MAX_PATH]; + HKEY hkey_product, hkey_patch, hkey_patches, hkey_udprops, hkey_udproduct; + HKEY hkey_udpatch, hkey_udpatches, hkey_udproductpatches, hkey_udproductpatch; + DWORD size; + LONG res; + + create_test_guid(patch_code, patch_squashed); + create_test_guid(prod_code, prod_squashed); + MultiByteToWideChar(CP_ACP, 0, patch_code, -1, patch_codeW, MAX_PATH); + + r = MsiGetPatchInfoA(NULL, NULL, NULL, NULL); + ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r); + + r = MsiGetPatchInfoA(patch_code, NULL, NULL, NULL); + ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r); + + r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, NULL, NULL); + ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r); + + size = 0; + r = MsiGetPatchInfoA(patch_code, NULL, NULL, &size); + ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r); + + r = MsiGetPatchInfoA(patch_code, "", NULL, &size); + ok(r == ERROR_UNKNOWN_PROPERTY, "expected ERROR_UNKNOWN_PROPERTY, got %u\n", r); + + lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\"); + lstrcatA(keypath, prod_squashed); + + res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey_product); + ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res); + + /* product key exists */ + size = MAX_PATH; + lstrcpyA(val, "apple"); + r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size); + ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r); + ok(!lstrcmpA(val, "apple"), "expected val to be unchanged, got \"%s\"\n", val); + ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size); + + res = RegCreateKeyA(hkey_product, "Patches", &hkey_patches); + ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res); + + /* patches key exists */ + size = MAX_PATH; + lstrcpyA(val, "apple"); + r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size); + ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r); + ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val); + ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size); + + res = RegCreateKeyA(hkey_patches, patch_squashed, &hkey_patch); + ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res); + + /* patch key exists */ + size = MAX_PATH; + lstrcpyA(val, "apple"); + r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size); + ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r); + ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val); + ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size); + + lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer"); + lstrcatA(keypath, "\\UserData\\S-1-5-18\\Products\\"); + lstrcatA(keypath, prod_squashed); + + res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey_udproduct); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res); + + /* UserData product key exists */ + size = MAX_PATH; + lstrcpyA(val, "apple"); + r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size); + ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r); + ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val); + ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size); + + res = RegCreateKeyA(hkey_udproduct, "InstallProperties", &hkey_udprops); + ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res); + + /* InstallProperties key exists */ + size = MAX_PATH; + lstrcpyA(val, "apple"); + r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size); + ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r); + ok(!lstrcmpA(val, "apple"), "expected val to be unchanged, got \"%s\"\n", val); + ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size); + + res = RegCreateKeyA(hkey_udproduct, "Patches", &hkey_udpatches); + ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res); + + /* UserData Patches key exists */ + size = MAX_PATH; + lstrcpyA(val, "apple"); + r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size); + ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r); + ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val); + ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size); + + res = RegCreateKeyA(hkey_udproduct, "Patches", &hkey_udproductpatches); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + res = RegCreateKeyA(hkey_udproductpatches, patch_squashed, &hkey_udproductpatch); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* UserData product patch key exists */ + size = MAX_PATH; + lstrcpyA(val, "apple"); + r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size); + ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT got %u\n", r); + ok(!lstrcmpA(val, "apple"), "expected val to be unchanged got \"%s\"\n", val); + ok(size == MAX_PATH, "expected size to be unchanged got %u\n", size); + + lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer"); + lstrcatA(keypath, "\\UserData\\S-1-5-18\\Patches\\"); + lstrcatA(keypath, patch_squashed); + + res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey_udpatch); + ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res); + + res = RegSetValueExA(hkey_udpatch, "LocalPackage", 0, REG_SZ, (const BYTE *)"c:\\test.msp", 12); + ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS got %d\n", res); + + /* UserData Patch key exists */ + size = 0; + lstrcpyA(val, "apple"); + r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size); + ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", r); + ok(!lstrcmpA(val, "apple"), "expected \"apple\", got \"%s\"\n", val); + ok(size == 11, "expected 11 got %u\n", size); + + size = MAX_PATH; + lstrcpyA(val, "apple"); + r = MsiGetPatchInfoA(patch_code, INSTALLPROPERTY_LOCALPACKAGEA, val, &size); + ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS got %u\n", r); + ok(!lstrcmpA(val, "c:\\test.msp"), "expected \"c:\\test.msp\", got \"%s\"\n", val); + ok(size == 11, "expected 11 got %u\n", size); + + size = 0; + valW[0] = 0; + r = MsiGetPatchInfoW(patch_codeW, INSTALLPROPERTY_LOCALPACKAGEW, valW, &size); + ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", r); + ok(!valW[0], "expected 0 got %u\n", valW[0]); + ok(size == 11, "expected 11 got %u\n", size); + + size = MAX_PATH; + valW[0] = 0; + r = MsiGetPatchInfoW(patch_codeW, INSTALLPROPERTY_LOCALPACKAGEW, valW, &size); + ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS got %u\n", r); + ok(valW[0], "expected > 0 got %u\n", valW[0]); + ok(size == 11, "expected 11 got %u\n", size); + + RegDeleteKeyA(hkey_udproductpatch, ""); + RegCloseKey(hkey_udproductpatch); + RegDeleteKeyA(hkey_udproductpatches, ""); + RegCloseKey(hkey_udproductpatches); + RegDeleteKeyA(hkey_udpatch, ""); + RegCloseKey(hkey_udpatch); + RegDeleteKeyA(hkey_patches, ""); + RegCloseKey(hkey_patches); + RegDeleteKeyA(hkey_product, ""); + RegCloseKey(hkey_product); + RegDeleteKeyA(hkey_patch, ""); + RegCloseKey(hkey_patch); + RegDeleteKeyA(hkey_udpatches, ""); + RegCloseKey(hkey_udpatches); + RegDeleteKeyA(hkey_udprops, ""); + RegCloseKey(hkey_udprops); + RegDeleteKeyA(hkey_udproduct, ""); + RegCloseKey(hkey_udproduct); +} + static void test_MsiEnumProducts(void) { UINT r; @@ -10985,6 +11162,7 @@ START_TEST(msi) test_MsiEnumPatchesEx(); test_MsiEnumPatches(); test_MsiGetPatchInfoEx(); + test_MsiGetPatchInfo(); test_MsiEnumProducts(); } diff --git a/include/msi.h b/include/msi.h index 5c2f38cc824..b331057d53c 100644 --- a/include/msi.h +++ b/include/msi.h @@ -503,6 +503,10 @@ UINT WINAPI MsiGetPatchInfoExA(LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR UINT WINAPI MsiGetPatchInfoExW(LPCWSTR, LPCWSTR, LPCWSTR, MSIINSTALLCONTEXT, LPCWSTR, LPWSTR, LPDWORD); #define MsiGetPatchInfoEx WINELIB_NAME_AW(MsiGetPatchInfoEx) +UINT WINAPI MsiGetPatchInfoA(LPCSTR, LPCSTR, LPSTR, LPDWORD); +UINT WINAPI MsiGetPatchInfoW(LPCWSTR, LPCWSTR, LPWSTR, LPDWORD); +#define MsiGetPatchInfo WINELIB_NAME_AW(MsiGetPatchInfo) + UINT WINAPI MsiEnableLogA(DWORD, LPCSTR, DWORD); UINT WINAPI MsiEnableLogW(DWORD, LPCWSTR, DWORD); #define MsiEnableLog WINELIB_NAME_AW(MsiEnableLog)