msi: Implement and test MsiGetPatchInfoA/W.

Hans Leidekker hans at codeweavers.com
Mon Feb 15 09:18:30 CST 2010


---
 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 4d9da4c..0735640 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 1475028..30daec9 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 e3baa09..2995adb 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 5c2f38c..b331057 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)
-- 
1.6.3.3




More information about the wine-patches mailing list