+static void test_MsiProvideQualifiedComponentEx(void)
+{
+ UINT r;
+ INSTALLSTATE state;
+ char comp[39], comp_squashed[33], comp2[39], comp2_base85[21], comp2_squashed[33];
+ char prod[39], prod_base85[21], prod_squashed[33];
+ char desc[MAX_PATH], buf[MAX_PATH], keypath[MAX_PATH], path[MAX_PATH];
+ DWORD len = sizeof(buf);
+ REGSAM access = KEY_ALL_ACCESS;
+ HKEY hkey, hkey2, hkey3, hkey4, hkey5;
+ LONG res;
+
+ if (is_process_limited())
+ {
+ skip( "process is limited\n" );
+ return;
+ }
+
+ create_test_guid( comp, comp_squashed );
+ compose_base85_guid( comp2, comp2_base85, comp2_squashed );
+ compose_base85_guid( prod, prod_base85, prod_squashed );
+
+ r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
+ ok( r == ERROR_UNKNOWN_COMPONENT, "got %u\n", r );
+
+ lstrcpyA( keypath, "Software\\Classes\\Installer\\Components\\" );
+ lstrcatA( keypath, comp_squashed );
+
+ if (is_wow64) access |= KEY_WOW64_64KEY;
+ res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey, NULL );
+ ok( res == ERROR_SUCCESS, "got %d\n", res );
+
+ lstrcpyA( desc, prod_base85 );
+ memcpy( desc + lstrlenA(desc), "feature<\0", sizeof("feature<\0") );
+ res = RegSetValueExA( hkey, "qualifier", 0, REG_MULTI_SZ, (const BYTE *)desc,
+ lstrlenA(prod_base85) + sizeof("feature<\0") );
+ ok( res == ERROR_SUCCESS, "got %d\n", res );
+
+ r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
+ ok( r == ERROR_UNKNOWN_PRODUCT, "got %u\n", r );
+
+ r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, NULL, 0, 0, buf, &len );
+ ok( r == ERROR_UNKNOWN_PRODUCT, "got %u\n", r );
+
+ state = MsiQueryProductStateA( prod );
+ ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
+
+ lstrcpyA( keypath, "Software\\Classes\\Installer\\Products\\" );
+ lstrcatA( keypath, prod_squashed );
+
+ res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey2, NULL );
+ ok( res == ERROR_SUCCESS, "got %d\n", res );
+
+ state = MsiQueryProductStateA( prod );
+ ok( state == INSTALLSTATE_ADVERTISED, "got %d\n", state );
+
+ r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
+ todo_wine ok( r == ERROR_UNKNOWN_FEATURE, "got %u\n", r );
+
+ lstrcpyA( keypath, "Software\\Classes\\Installer\\Features\\" );
+ lstrcatA( keypath, prod_squashed );
+
+ res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey3, NULL );
+ ok( res == ERROR_SUCCESS, "got %d\n", res );
+
+ state = MsiQueryFeatureStateA( prod, "feature" );
+ ok( state == INSTALLSTATE_UNKNOWN, "got %d\n", state );
+
+ res = RegSetValueExA( hkey3, "feature", 0, REG_SZ, (const BYTE *)"", 1 );
+ ok( res == ERROR_SUCCESS, "got %d\n", res );
+
+ state = MsiQueryFeatureStateA( prod, "feature" );
+ ok( state == INSTALLSTATE_ADVERTISED, "got %d\n", state );
+
+ r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
+ ok( r == ERROR_FILE_NOT_FOUND, "got %u\n", r );
+
+ len = sizeof(buf);
+ r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, NULL, 0, 0, buf, &len );
+ ok( r == ERROR_FILE_NOT_FOUND, "got %u\n", r );
+
+ lstrcpyA( keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\" );
+ lstrcatA( keypath, prod_squashed );
+ lstrcatA( keypath, "\\Features" );
+
+ res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey4, NULL );
+ ok( res == ERROR_SUCCESS, "got %d\n", res );
+
+ res = RegSetValueExA( hkey4, "feature", 0, REG_SZ, (const BYTE *)comp2_base85, sizeof(comp2_base85) );
+ ok( res == ERROR_SUCCESS, "got %d\n", res );
+
+ state = MsiQueryFeatureStateA( prod, "feature" );
+ ok( state == INSTALLSTATE_ADVERTISED, "got %d\n", state );
+
+ lstrcpyA( keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\" );
+ lstrcatA( keypath, comp2_squashed );
+
+ res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &hkey5, NULL );
+ ok( res == ERROR_SUCCESS, "got %d\n", res );
+
+ res = RegSetValueExA( hkey5, prod_squashed, 0, REG_SZ, (const BYTE *)"c:\\nosuchfile", sizeof("c:\\nosuchfile") );
+ ok( res == ERROR_SUCCESS, "got %d\n", res );
+
+ state = MsiQueryFeatureStateA( prod, "feature" );
+ ok( state == INSTALLSTATE_LOCAL, "got %d\n", state );
+
+ r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
+ ok( r == ERROR_FILE_NOT_FOUND, "got %u\n", r );
+
+ GetCurrentDirectoryA( MAX_PATH, path );
+ lstrcatA( path, "\\msitest" );
+ CreateDirectoryA( path, NULL );
+ lstrcatA( path, "\\test.txt" );
+ create_file( path, "test", 100 );
+
+ res = RegSetValueExA( hkey5, prod_squashed, 0, REG_SZ, (const BYTE *)path, lstrlenA(path) + 1 );
+ ok( res == ERROR_SUCCESS, "got %d\n", res );
+
+ buf[0] = 0;
+ len = sizeof(buf);
+ r = MsiProvideQualifiedComponentExA( comp, "qualifier", INSTALLMODE_EXISTING, prod, 0, 0, buf, &len );
+ ok( r == ERROR_SUCCESS, "got %u\n", r );
+ ok( len == lstrlenA(path), "got %u\n", len );
+ ok( !lstrcmpA( path, buf ), "got '%s'\n", buf );
+
+ DeleteFileA( "msitest\\text.txt" );
+ RemoveDirectoryA( "msitest" );
+
+ delete_key( hkey5, "", access & KEY_WOW64_64KEY );
+ RegCloseKey( hkey5 );
+ delete_key( hkey4, "", access & KEY_WOW64_64KEY );
+ RegCloseKey( hkey4 );
+ delete_key( hkey3, "", access & KEY_WOW64_64KEY );
+ RegCloseKey( hkey3 );
+ delete_key( hkey2, "", access & KEY_WOW64_64KEY );
+ RegCloseKey( hkey2 );
+ delete_key( hkey, "", access & KEY_WOW64_64KEY );
+ RegCloseKey( hkey );
+}
+