[MSI_WINETEST]
[reactos.git] / rostests / winetests / msi / msi.c
index 6ba0e11..da6b446 100644 (file)
@@ -55,6 +55,10 @@ static INSTALLSTATE (WINAPI *pMsiUseFeatureExA)
     (LPCSTR, LPCSTR ,DWORD, DWORD);
 static UINT (WINAPI *pMsiGetPatchInfoExA)
     (LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, LPSTR, DWORD *);
+static UINT (WINAPI *pMsiEnumProductsExA)
+    (LPCSTR, LPCSTR, DWORD, DWORD, CHAR[39], MSIINSTALLCONTEXT *, LPSTR, LPDWORD);
+static UINT (WINAPI *pMsiEnumComponentsExA)
+    (LPCSTR, DWORD, DWORD, CHAR[39], MSIINSTALLCONTEXT *, LPSTR, LPDWORD);
 
 static void init_functionpointers(void)
 {
@@ -76,6 +80,8 @@ static void init_functionpointers(void)
     GET_PROC(hmsi, MsiQueryComponentStateA)
     GET_PROC(hmsi, MsiUseFeatureExA)
     GET_PROC(hmsi, MsiGetPatchInfoExA)
+    GET_PROC(hmsi, MsiEnumProductsExA)
+    GET_PROC(hmsi, MsiEnumComponentsExA)
 
     GET_PROC(hadvapi32, ConvertSidToStringSidA)
     GET_PROC(hadvapi32, RegDeleteKeyExA)
@@ -411,6 +417,12 @@ static const struct
     MSIFILEHASHINFO hash;
 } hash_data[] =
 {
+    { "", 0,
+      { HASHSIZE,
+        { 0, 0, 0, 0 },
+      },
+    },
+
     { "abc", 0,
       { HASHSIZE,
         { 0x98500190, 0xb04fd23c, 0x7d3f96d6, 0x727fe128 },
@@ -538,8 +550,11 @@ static void create_test_guid(LPSTR prodcode, LPSTR squashed)
     ok(size == 39, "Expected 39, got %d\n", hr);
 
     WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL);
-    squash_guid(guidW, squashedW);
-    WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
+    if (squashed)
+    {
+        squash_guid(guidW, squashedW);
+        WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
+    }
 }
 
 static char *get_user_sid(void)
@@ -1631,10 +1646,10 @@ static void test_MsiQueryComponentState(void)
     ok(state == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", state);
     ok(error == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", error);
 
-    res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01", 3);
+    res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"01:", 4);
     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
 
-    /* bad INSTALLSTATE_SOURCE */
+    /* registry component */
     state = MAGIC_ERROR;
     SetLastError(0xdeadbeef);
     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
@@ -11788,12 +11803,340 @@ static void test_MsiGetFileSignatureInformation(void)
     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, NULL, NULL, &len );
     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got 0x%08x\n", hr);
 
+    cert = (const CERT_CONTEXT *)0xdeadbeef;
     hr = MsiGetFileSignatureInformationA( "signature.bin", 0, &cert, NULL, &len );
     todo_wine ok(hr == HRESULT_FROM_WIN32(ERROR_FUNCTION_FAILED), "got 0x%08x\n", hr);
+    ok(cert == NULL, "got %p\n", cert);
 
     DeleteFileA( "signature.bin" );
 }
 
+static void test_MsiEnumProductsEx(void)
+{
+    UINT r;
+    DWORD len, index;
+    MSIINSTALLCONTEXT context;
+    char product0[39], product1[39], product2[39], product3[39], guid[39], sid[128];
+    char product_squashed1[33], product_squashed2[33], product_squashed3[33];
+    char keypath1[MAX_PATH], keypath2[MAX_PATH], keypath3[MAX_PATH];
+    HKEY key1 = NULL, key2 = NULL, key3 = NULL;
+    REGSAM access = KEY_ALL_ACCESS;
+    char *usersid = get_user_sid();
+
+    if (!pMsiEnumProductsExA)
+    {
+        win_skip("MsiEnumProductsExA not implemented\n");
+        return;
+    }
+
+    create_test_guid( product0, NULL );
+    create_test_guid( product1, product_squashed1 );
+    create_test_guid( product2, product_squashed2 );
+    create_test_guid( product3, product_squashed3 );
+
+    if (is_wow64) access |= KEY_WOW64_64KEY;
+
+    strcpy( keypath1, "Software\\Classes\\Installer\\Products\\" );
+    strcat( keypath1, product_squashed1 );
+
+    r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
+    if (r == ERROR_ACCESS_DENIED)
+    {
+        skip( "insufficient rights\n" );
+        goto done;
+    }
+    ok( r == ERROR_SUCCESS, "got %u\n", r );
+
+    strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\" );
+    strcat( keypath2, usersid );
+    strcat( keypath2, "\\Installer\\Products\\" );
+    strcat( keypath2, product_squashed2 );
+
+    r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
+    ok( r == ERROR_SUCCESS, "got %u\n", r );
+
+    strcpy( keypath3, usersid );
+    strcat( keypath3, "\\Software\\Microsoft\\Installer\\Products\\" );
+    strcat( keypath3, product_squashed3 );
+
+    r = RegCreateKeyExA( HKEY_USERS, keypath3, 0, NULL, 0, access, NULL, &key3, NULL );
+    ok( r == ERROR_SUCCESS, "got %u\n", r );
+
+    r = pMsiEnumProductsExA( NULL, NULL, 0, 0, NULL, NULL, NULL, NULL );
+    ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
+
+    len = sizeof(sid);
+    r = pMsiEnumProductsExA( NULL, NULL, 0, 0, NULL, NULL, NULL, &len );
+    ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
+    ok( len == sizeof(sid), "got %u\n", len );
+
+    r = pMsiEnumProductsExA( NULL, NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, NULL, NULL );
+    ok( r == ERROR_SUCCESS, "got %u\n", r );
+
+    sid[0] = 0;
+    len = sizeof(sid);
+    r = pMsiEnumProductsExA( product0, NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, &len );
+    ok( r == ERROR_NO_MORE_ITEMS, "got %u\n", r );
+    ok( len == sizeof(sid), "got %u\n", len );
+    ok( !sid[0], "got %s\n", sid );
+
+    sid[0] = 0;
+    len = sizeof(sid);
+    r = pMsiEnumProductsExA( product0, usersid, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, &len );
+    ok( r == ERROR_NO_MORE_ITEMS, "got %u\n", r );
+    ok( len == sizeof(sid), "got %u\n", len );
+    ok( !sid[0], "got %s\n", sid );
+
+    sid[0] = 0;
+    len = 0;
+    r = pMsiEnumProductsExA( NULL, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, 0, NULL, NULL, sid, &len );
+    ok( r == ERROR_MORE_DATA, "got %u\n", r );
+    ok( len, "length unchanged\n" );
+    ok( !sid[0], "got %s\n", sid );
+
+    guid[0] = 0;
+    context = 0xdeadbeef;
+    sid[0] = 0;
+    len = sizeof(sid);
+    r = pMsiEnumProductsExA( NULL, NULL, MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
+    ok( r == ERROR_SUCCESS, "got %u\n", r );
+    ok( guid[0], "empty guid\n" );
+    ok( context != 0xdeadbeef, "context unchanged\n" );
+    ok( !len, "got %u\n", len );
+    ok( !sid[0], "got %s\n", sid );
+
+    guid[0] = 0;
+    context = 0xdeadbeef;
+    sid[0] = 0;
+    len = sizeof(sid);
+    r = pMsiEnumProductsExA( NULL, usersid, MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
+    ok( r == ERROR_SUCCESS, "got %u\n", r );
+    ok( guid[0], "empty guid\n" );
+    ok( context != 0xdeadbeef, "context unchanged\n" );
+    ok( !len, "got %u\n", len );
+    ok( !sid[0], "got %s\n", sid );
+
+    guid[0] = 0;
+    context = 0xdeadbeef;
+    sid[0] = 0;
+    len = sizeof(sid);
+    r = pMsiEnumProductsExA( NULL, "S-1-1-0", MSIINSTALLCONTEXT_ALL, 0, guid, &context, sid, &len );
+    if (r == ERROR_ACCESS_DENIED)
+    {
+        skip( "insufficient rights\n" );
+        goto done;
+    }
+    ok( r == ERROR_SUCCESS, "got %u\n", r );
+    ok( guid[0], "empty guid\n" );
+    ok( context != 0xdeadbeef, "context unchanged\n" );
+    ok( !len, "got %u\n", len );
+    ok( !sid[0], "got %s\n", sid );
+
+    index = 0;
+    guid[0] = 0;
+    context = 0xdeadbeef;
+    sid[0] = 0;
+    len = sizeof(sid);
+    while (!pMsiEnumProductsExA( NULL, "S-1-1-0", MSIINSTALLCONTEXT_ALL, index, guid, &context, sid, &len ))
+    {
+        if (!strcmp( product1, guid ))
+        {
+            ok( context == MSIINSTALLCONTEXT_MACHINE, "got %u\n", context );
+            ok( !sid[0], "got \"%s\"\n", sid );
+            ok( !len, "unexpected length %u\n", len );
+        }
+        if (!strcmp( product2, guid ))
+        {
+            ok( context == MSIINSTALLCONTEXT_USERMANAGED, "got %u\n", context );
+            ok( sid[0], "empty sid\n" );
+            ok( len == strlen(sid), "unexpected length %u\n", len );
+        }
+        if (!strcmp( product3, guid ))
+        {
+            ok( context == MSIINSTALLCONTEXT_USERUNMANAGED, "got %u\n", context );
+            ok( sid[0], "empty sid\n" );
+            ok( len == strlen(sid), "unexpected length %u\n", len );
+        }
+        index++;
+        guid[0] = 0;
+        context = 0xdeadbeef;
+        sid[0] = 0;
+        len = sizeof(sid);
+    }
+
+done:
+    delete_key( key1, "", access );
+    delete_key( key2, "", access );
+    delete_key( key3, "", access );
+    RegCloseKey( key1 );
+    RegCloseKey( key2 );
+    RegCloseKey( key3 );
+    LocalFree( usersid );
+}
+
+static void test_MsiEnumComponents(void)
+{
+    UINT r;
+    int found1, found2;
+    DWORD index;
+    char comp1[39], comp2[39], guid[39];
+    char comp_squashed1[33], comp_squashed2[33];
+    char keypath1[MAX_PATH], keypath2[MAX_PATH];
+    REGSAM access = KEY_ALL_ACCESS;
+    char *usersid = get_user_sid();
+    HKEY key1 = NULL, key2 = NULL;
+
+    create_test_guid( comp1, comp_squashed1 );
+    create_test_guid( comp2, comp_squashed2 );
+
+    if (is_wow64) access |= KEY_WOW64_64KEY;
+
+    strcpy( keypath1, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
+    strcat( keypath1, "S-1-5-18\\Components\\" );
+    strcat( keypath1, comp_squashed1 );
+
+    r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
+    if (r == ERROR_ACCESS_DENIED)
+    {
+        skip( "insufficient rights\n" );
+        goto done;
+    }
+    ok( r == ERROR_SUCCESS, "got %u\n", r );
+
+    strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
+    strcat( keypath2, usersid );
+    strcat( keypath2, "\\Components\\" );
+    strcat( keypath2, comp_squashed2 );
+
+    r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
+    if (r == ERROR_ACCESS_DENIED)
+    {
+        skip( "insufficient rights\n" );
+        goto done;
+    }
+
+    r = MsiEnumComponentsA( 0, NULL );
+    ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
+
+    index = 0;
+    guid[0] = 0;
+    found1 = found2 = 0;
+    while (!MsiEnumComponentsA( index, guid ))
+    {
+        if (!strcmp( guid, comp1 )) found1 = 1;
+        if (!strcmp( guid, comp2 )) found2 = 1;
+        ok( guid[0], "empty guid\n" );
+        guid[0] = 0;
+        index++;
+    }
+    ok( found1, "comp1 not found\n" );
+    ok( found2, "comp2 not found\n" );
+
+done:
+    delete_key( key1, "", access );
+    delete_key( key2, "", access );
+    RegCloseKey( key1 );
+    RegCloseKey( key2 );
+    LocalFree( usersid );
+}
+
+static void test_MsiEnumComponentsEx(void)
+{
+    UINT r;
+    int found1, found2;
+    DWORD len, index;
+    MSIINSTALLCONTEXT context;
+    char comp1[39], comp2[39], guid[39], sid[128];
+    char comp_squashed1[33], comp_squashed2[33];
+    char keypath1[MAX_PATH], keypath2[MAX_PATH];
+    HKEY key1 = NULL, key2 = NULL;
+    REGSAM access = KEY_ALL_ACCESS;
+    char *usersid = get_user_sid();
+
+    if (!pMsiEnumComponentsExA)
+    {
+        win_skip( "MsiEnumComponentsExA not implemented\n" );
+        return;
+    }
+    create_test_guid( comp1, comp_squashed1 );
+    create_test_guid( comp2, comp_squashed2 );
+
+    if (is_wow64) access |= KEY_WOW64_64KEY;
+
+    strcpy( keypath1, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
+    strcat( keypath1, "S-1-5-18\\Components\\" );
+    strcat( keypath1, comp_squashed1 );
+
+    r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
+    if (r == ERROR_ACCESS_DENIED)
+    {
+        skip( "insufficient rights\n" );
+        goto done;
+    }
+    ok( r == ERROR_SUCCESS, "got %u\n", r );
+
+    strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
+    strcat( keypath2, usersid );
+    strcat( keypath2, "\\Components\\" );
+    strcat( keypath2, comp_squashed2 );
+
+    r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
+    if (r == ERROR_ACCESS_DENIED)
+    {
+        skip( "insufficient rights\n" );
+        goto done;
+    }
+    ok( r == ERROR_SUCCESS, "got %u\n", r );
+    r = RegSetValueExA( key2, comp_squashed2, 0, REG_SZ, (const BYTE *)"c:\\doesnotexist",
+                        sizeof("c:\\doesnotexist"));
+    ok( r == ERROR_SUCCESS, "got %u\n", r );
+
+    index = 0;
+    guid[0] = 0;
+    context = 0xdeadbeef;
+    sid[0] = 0;
+    len = sizeof(sid);
+    found1 = found2 = 0;
+    while (!pMsiEnumComponentsExA( "S-1-1-0", MSIINSTALLCONTEXT_ALL, index, guid, &context, sid, &len ))
+    {
+        if (!strcmp( comp1, guid ))
+        {
+            ok( context == MSIINSTALLCONTEXT_MACHINE, "got %u\n", context );
+            ok( !sid[0], "got \"%s\"\n", sid );
+            ok( !len, "unexpected length %u\n", len );
+            found1 = 1;
+        }
+        if (!strcmp( comp2, guid ))
+        {
+            ok( context == MSIINSTALLCONTEXT_USERUNMANAGED, "got %u\n", context );
+            ok( sid[0], "empty sid\n" );
+            ok( len == strlen(sid), "unexpected length %u\n", len );
+            found2 = 1;
+        }
+        index++;
+        guid[0] = 0;
+        context = 0xdeadbeef;
+        sid[0] = 0;
+        len = sizeof(sid);
+    }
+    ok( found1, "comp1 not found\n" );
+    ok( found2, "comp2 not found\n" );
+
+    r = pMsiEnumComponentsExA( NULL, 0, 0, NULL, NULL, NULL, NULL );
+    ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
+
+    r = pMsiEnumComponentsExA( NULL, MSIINSTALLCONTEXT_ALL, 0, NULL, NULL, sid, NULL );
+    ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
+
+done:
+    RegDeleteValueA( key2, comp_squashed2 );
+    delete_key( key1, "", access );
+    delete_key( key2, "", access );
+    RegCloseKey( key1 );
+    RegCloseKey( key2 );
+    LocalFree( usersid );
+}
+
 START_TEST(msi)
 {
     init_functionpointers();
@@ -11826,6 +12169,9 @@ START_TEST(msi)
         test_MsiGetPatchInfoEx();
         test_MsiGetPatchInfo();
         test_MsiEnumProducts();
+        test_MsiEnumProductsEx();
+        test_MsiEnumComponents();
+        test_MsiEnumComponentsEx();
     }
     test_MsiGetFileVersion();
     test_MsiGetFileSignatureInformation();