Author: akhaldi
Date: Mon Mar  9 20:28:54 2015
New Revision: 66633
URL: 
http://svn.reactos.org/svn/reactos?rev=66633&view=rev
Log:
[MSI_WINETEST] Sync with Wine Staging 1.7.37. CORE-9246
Modified:
    trunk/rostests/winetests/msi/action.c
    trunk/rostests/winetests/msi/automation.c
    trunk/rostests/winetests/msi/db.c
    trunk/rostests/winetests/msi/install.c
    trunk/rostests/winetests/msi/msi.c
    trunk/rostests/winetests/msi/package.c
    trunk/rostests/winetests/msi/source.c
Modified: trunk/rostests/winetests/msi/action.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/msi/action.c?re…
==============================================================================
--- trunk/rostests/winetests/msi/action.c       [iso-8859-1] (original)
+++ trunk/rostests/winetests/msi/action.c       [iso-8859-1] Mon Mar  9 20:28:54 2015
@@ -182,7 +182,8 @@
     "SERVNAME2\tTestService2\n"
     "SERVDISP\tTestServiceDisp\n"
     "SERVDISP2\tTestServiceDisp2\n"
-    "MSIFASTINSTALL\t1\n";
+    "MSIFASTINSTALL\t1\n"
+    "regdata15\t#x01\n";
 static const char environment_dat[] =
     "Environment\tName\tValue\tComponent_\n"
@@ -242,7 +243,10 @@
     "ServiceControl\tName\tEvent\tArguments\tWait\tComponent_\n"
     "s72\tl255\ti2\tL255\tI2\ts72\n"
     "ServiceControl\tServiceControl\n"
-    "ServiceControl\tSpooler\t1\t\t0\tservice_comp";
+    "ServiceControl\tSpooler\t1\t\t1\tservice_comp\n"
+    "ServiceControl2\tSpooler\t2\t\t1\tservice_comp\n"
+    "ServiceControl3\tSpooler\t16\t\t1\tservice_comp\n"
+    "ServiceControl4\tSpooler\t32\t\t1\tservice_comp\n";
 static const char sss_install_exec_seq_dat[] =
     "Action\tCondition\tSequence\n"
@@ -255,11 +259,15 @@
     "CostFinalize\t\t1000\n"
     "InstallValidate\t\t1400\n"
     "InstallInitialize\t\t1500\n"
+    "StopServices\t\t4000\n"
     "DeleteServices\t\t5000\n"
     "MoveFiles\t\t5100\n"
     "InstallFiles\t\t5200\n"
     "DuplicateFiles\t\t5300\n"
     "StartServices\t\t5400\n"
+    "RegisterProduct\t\t5500\n"
+    "PublishFeatures\t\t5600\n"
+    "PublishProduct\t\t5700\n"
     "InstallFinalize\t\t6000\n";
 static const char sds_install_exec_seq_dat[] =
@@ -510,7 +518,11 @@
     "regdata8\t2\tSOFTWARE\\Wine\\msitest\tValue4\tone[~]two\taugustus\n"
"regdata9\t2\tSOFTWARE\\Wine\\msitest\tValue5\t[~]one[~]two[~]three\taugustus\n"
     "regdata10\t2\tSOFTWARE\\Wine\\msitest\tValue6\t[~]\taugustus\n"
-    "regdata11\t2\tSOFTWARE\\Wine\\msitest\tValue7\t[~]two\taugustus\n";
+    "regdata11\t2\tSOFTWARE\\Wine\\msitest\tValue7\t[~]two\taugustus\n"
+    "regdata12\t2\tSOFTWARE\\Wine\\msitest\tValue8\t#1\taugustus\n"
+    "regdata13\t2\tSOFTWARE\\Wine\\msitest\tValue9\t#x1\taugustus\n"
+    "regdata14\t2\tSOFTWARE\\Wine\\msitest\tValue10\t#x01\taugustus\n"
+    "regdata15\t2\tSOFTWARE\\Wine\\msitest\tValue11\t[regdata15]\taugustus\n";
 static const char cf_directory_dat[] =
     "Directory\tDirectory_Parent\tDefaultDir\n"
@@ -2706,7 +2718,7 @@
     }
     if (!expected)
-        ok_(__FILE__, line)(lstrlenA(val) == 0, "Expected empty string, got
%s\n", val);
+        ok_(__FILE__, line)(!val[0], "Expected empty string, got %s\n", val);
     else
     {
         if (bcase)
@@ -4919,6 +4931,7 @@
     HKEY hkey;
     DWORD type, size;
     CHAR path[MAX_PATH];
+    BYTE buf[8];
     if (is_process_limited())
     {
@@ -5050,6 +5063,42 @@
     ok(!memcmp(path, "two\0", size), "Wrong multi-sz data\n");
     ok(size == 5, "Expected 5, got %d\n", size);
     ok(type == REG_MULTI_SZ, "Expected REG_MULTI_SZ, got %d\n", type);
+
+    size = sizeof(buf);
+    type = 0xdeadbeef;
+    memset(buf, 0, size);
+    res = RegQueryValueExA(hkey, "Value8", NULL, &type, buf, &size);
+    ok(res == ERROR_SUCCESS, "got %u\n", res);
+    ok(*(DWORD *)buf == 1, "got %u\n", *(DWORD *)buf);
+    ok(size == 4, "got %u\n", size);
+    ok(type == REG_DWORD, "got %u\n", type);
+
+    size = sizeof(buf);
+    type = 0xdeadbeef;
+    memset(buf, 0, size);
+    res = RegQueryValueExA(hkey, "Value9", NULL, &type, buf, &size);
+    ok(res == ERROR_SUCCESS, "got %u\n", res);
+    ok(buf[0] == 1, "got %u\n", buf[0]);
+    ok(size == 1, "got %u\n", size);
+    ok(type == REG_BINARY, "got %u\n", type);
+
+    size = sizeof(buf);
+    type = 0xdeadbeef;
+    memset(buf, 0, size);
+    res = RegQueryValueExA(hkey, "Value10", NULL, &type, buf, &size);
+    ok(res == ERROR_SUCCESS, "got %u\n", res);
+    ok(buf[0] == 1, "got %u\n", buf[0]);
+    ok(size == 1, "got %u\n", size);
+    ok(type == REG_BINARY, "got %u\n", type);
+
+    size = sizeof(buf);
+    type = 0xdeadbeef;
+    memset(buf, 0, size);
+    res = RegQueryValueExA(hkey, "Value11", NULL, &type, buf, &size);
+    ok(res == ERROR_SUCCESS, "got %u\n", res);
+    ok(buf[0] == 1, "got %u\n", buf[0]);
+    ok(size == 1, "got %u\n", size);
+    ok(type == REG_BINARY, "got %u\n", type);
     RegDeleteValueA(hkey, "Value");
     RegDeleteValueA(hkey, "Value1");
@@ -5059,6 +5108,10 @@
     RegDeleteValueA(hkey, "Value5");
     RegDeleteValueA(hkey, "Value6");
     RegDeleteValueA(hkey, "Value7");
+    RegDeleteValueA(hkey, "Value8");
+    RegDeleteValueA(hkey, "Value9");
+    RegDeleteValueA(hkey, "Value10");
+    RegDeleteValueA(hkey, "Value11");
     RegCloseKey(hkey);
     RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest");
@@ -5260,7 +5313,7 @@
     DeleteFileA(msifile);
 }
-static void test_start_services(void)
+static void test_start_stop_services(void)
 {
     UINT r;
     SC_HANDLE scm, service;
@@ -5307,6 +5360,23 @@
     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
     r = MsiInstallProductA(msifile, NULL);
+    ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
+
+    if (error == ERROR_SUCCESS)
+    {
+        SERVICE_STATUS status;
+
+        scm = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+        service = OpenServiceA(scm, "Spooler", SC_MANAGER_ALL_ACCESS);
+
+        ret = ControlService(service, SERVICE_CONTROL_STOP, &status);
+        ok(ret, "ControlService failed %u\n", GetLastError());
+
+        CloseServiceHandle(service);
+        CloseServiceHandle(scm);
+    }
+
+    r = MsiInstallProductA(msifile, "REMOVE=ALL");
     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not
installed\n");
@@ -5323,22 +5393,22 @@
     ok(delete_pf("msitest\\service2.exe", TRUE), "File not
installed\n");
     ok(delete_pf("msitest", FALSE), "Directory not created\n");
+    if (error == ERROR_SUCCESS)
+    {
+        SERVICE_STATUS status;
+
+        scm = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+        service = OpenServiceA(scm, "Spooler", SC_MANAGER_ALL_ACCESS);
+
+        ret = ControlService(service, SERVICE_CONTROL_STOP, &status);
+        ok(ret, "ControlService failed %u\n", GetLastError());
+
+        CloseServiceHandle(service);
+        CloseServiceHandle(scm);
+    }
+
     delete_test_files();
     DeleteFileA(msifile);
-
-    if (error == ERROR_SUCCESS)
-    {
-        SERVICE_STATUS status;
-
-        scm = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);
-        service = OpenServiceA(scm, "Spooler", SC_MANAGER_ALL_ACCESS);
-
-        ret = ControlService(service, SERVICE_CONTROL_STOP, &status);
-        ok(ret, "ControlService failed %u\n", GetLastError());
-
-        CloseServiceHandle(service);
-        CloseServiceHandle(scm);
-    }
 }
 static void test_delete_services(void)
@@ -6819,7 +6889,7 @@
     test_write_registry_values();
     test_envvar();
     test_create_remove_folder();
-    test_start_services();
+    test_start_stop_services();
     test_delete_services();
     test_install_services();
     test_self_registration();
Modified: trunk/rostests/winetests/msi/automation.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/msi/automation.…
==============================================================================
--- trunk/rostests/winetests/msi/automation.c   [iso-8859-1] (original)
+++ trunk/rostests/winetests/msi/automation.c   [iso-8859-1] Mon Mar  9 20:28:54 2015
@@ -1934,7 +1934,7 @@
     hr = Session_ModePut(pSession, MSIRUNMODE_REBOOTNOW, TRUE);
     ok(hr == S_OK, "Session_ModePut failed, hresult 0x%08x\n", hr);
-    if (hr == DISP_E_EXCEPTION) ok_exception(hr, szModeFlag);
+    ok_exception(hr, szModeFlag);
     hr = Session_ModeGet(pSession, MSIRUNMODE_REBOOTNOW, &bool);
     ok(hr == S_OK, "Session_ModeGet failed, hresult 0x%08x\n", hr);
@@ -1942,7 +1942,7 @@
     hr = Session_ModePut(pSession, MSIRUNMODE_REBOOTNOW, FALSE);  /* set it again so we
don't reboot */
     ok(hr == S_OK, "Session_ModePut failed, hresult 0x%08x\n", hr);
-    if (hr == DISP_E_EXCEPTION) ok_exception(hr, szModeFlag);
+    ok_exception(hr, szModeFlag);
     hr = Session_ModePut(pSession, MSIRUNMODE_MAINTENANCE, TRUE);
     ok(hr == DISP_E_EXCEPTION, "Session_ModePut failed, hresult 0x%08x\n", hr);
Modified: trunk/rostests/winetests/msi/db.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/msi/db.c?rev=66…
==============================================================================
--- trunk/rostests/winetests/msi/db.c   [iso-8859-1] (original)
+++ trunk/rostests/winetests/msi/db.c   [iso-8859-1] Mon Mar  9 20:28:54 2015
@@ -1670,6 +1670,28 @@
     MsiViewClose( view );
     MsiCloseHandle( view );
+    /* try again */
+    create_file( "test1.txt" );
+
+    rec = MsiCreateRecord( 2 );
+    MsiRecordSetStringA( rec, 1, "data1" );
+
+    r = MsiRecordSetStreamA( rec, 2, "test1.txt" );
+    ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r
);
+
+    DeleteFileA( "test1.txt" );
+
+    r = MsiDatabaseOpenViewA( hdb,
+            "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )",
&view );
+    ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r );
+
+    r = MsiViewExecute( view, rec );
+    ok( r == ERROR_FUNCTION_FAILED, "got %u\n", r );
+
+    MsiCloseHandle( rec );
+    MsiViewClose( view );
+    MsiCloseHandle( view );
+
     r = MsiDatabaseOpenViewA( hdb,
             "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` =
'data'", &view );
     ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
@@ -1759,7 +1781,7 @@
     memset(buf, 0, MAX_PATH);
     r = MsiRecordReadStream( rec, 2, buf, &size );
     ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
-    todo_wine ok( !lstrcmpA(buf, "test2.txt\n"), "Expected
'test2.txt\\n', got %s\n", buf);
+    ok( !lstrcmpA(buf, "test2.txt\n"), "Expected 'test2.txt\\n',
got %s\n", buf);
     MsiCloseHandle( rec );
     MsiViewClose( view );
@@ -1791,9 +1813,40 @@
     ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n",
r);
     DeleteFileA( "test.txt" );
+    /* try a name that exceeds maximum OLE stream name length */
+    query = "INSERT INTO `Binary` ( `Name`, `ID`, `Data` ) VALUES (
'encryption.dll.CB4E6205_F99A_4C51_ADD4_184506EFAB87', 10000, ? )";
+    r = run_query( hdb, rec, query );
+    ok( r == ERROR_SUCCESS, "Insert into Binary table failed: %d\n", r );
+
+    r = MsiCloseHandle( rec );
+    ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
+
+    r = MsiDatabaseCommit( hdb );
+    ok( r == ERROR_FUNCTION_FAILED , "got %u\n", r );
+
+    r = MsiCloseHandle( hdb );
+    ok( r == ERROR_SUCCESS , "Failed to close database\n" );
+
+    r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb );
+    ok( r == ERROR_SUCCESS , "Failed to open database\n" );
+
+    query = "CREATE TABLE `Binary` ( `Name` CHAR(72) NOT NULL, `ID` INT NOT NULL,
`Data` OBJECT  PRIMARY KEY `Name`, `ID`)";
+    r = run_query( hdb, 0, query );
+    ok( r == ERROR_SUCCESS, "Cannot create Binary table: %d\n", r );
+
+    create_file( "test.txt" );
+    rec = MsiCreateRecord( 1 );
+    r = MsiRecordSetStreamA( rec, 1, "test.txt" );
+    ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r
);
+    DeleteFileA( "test.txt" );
+
     query = "INSERT INTO `Binary` ( `Name`, `ID`, `Data` ) VALUES (
'filename1', 1, ? )";
     r = run_query( hdb, rec, query );
     ok( r == ERROR_SUCCESS, "Insert into Binary table failed: %d\n", r );
+
+    query = "INSERT INTO `Binary` ( `Name`, `ID`, `Data` ) VALUES (
'filename1', 1, ? )";
+    r = run_query( hdb, rec, query );
+    ok( r == ERROR_FUNCTION_FAILED, "got %u\n", r );
     r = MsiCloseHandle( rec );
     ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
@@ -4535,7 +4588,7 @@
     size = MAX_PATH;
     r = MsiRecordGetStringA(rec, 1, result, &size);
     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
-    ok(!lstrlenA(result), "Expected an empty string, got %s\n", result);
+    ok(!result[0], "Expected an empty string, got %s\n", result);
     MsiCloseHandle(rec);
@@ -4581,7 +4634,7 @@
     size = MAX_PATH;
     r = MsiRecordGetStringA(rec, 1, result, &size);
     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
-    ok(!lstrlenA(result), "Expected an empty string, got %s\n", result);
+    ok(!result[0], "Expected an empty string, got %s\n", result);
     MsiCloseHandle(rec);
Modified: trunk/rostests/winetests/msi/install.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/msi/install.c?r…
==============================================================================
--- trunk/rostests/winetests/msi/install.c      [iso-8859-1] (original)
+++ trunk/rostests/winetests/msi/install.c      [iso-8859-1] Mon Mar  9 20:28:54 2015
@@ -561,34 +561,10 @@
                                     "2\t2\t\ttest2.cab\tDISK2\t\n"
                                     "3\t12\t\ttest3.cab\tDISK3\t\n";
-static const CHAR ci_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
-                                              "s72\tS255\tI2\n"
-
"InstallExecuteSequence\tAction\n"
-                                              "CostFinalize\t\t1000\n"
-                                              "CostInitialize\t\t800\n"
-                                              "FileCost\t\t900\n"
-                                              "InstallFiles\t\t4000\n"
-                                              "InstallServices\t\t5000\n"
-                                              "InstallFinalize\t\t6600\n"
-                                              "InstallInitialize\t\t1500\n"
-                                              "RunInstall\t\t1600\n"
-                                              "InstallValidate\t\t1400\n"
-                                              "LaunchConditions\t\t100";
-
-static const CHAR ci_custom_action_dat[] =
"Action\tType\tSource\tTarget\tISComments\n"
-                                            "s72\ti2\tS64\tS0\tS255\n"
-                                            "CustomAction\tAction\n"
-
"RunInstall\t87\tmsitest\\concurrent.msi\tMYPROP=[UILevel]\t\n";
-
 static const CHAR ci_component_dat[] =
"Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
                                        "Component\tComponent\n"
"maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
-
-static const CHAR ci2_component_dat[] =
"Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
-                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
-                                        "Component\tComponent\n"
-                                        "augustus\t\tMSITESTDIR\t0\tUILevel=3 AND
MYPROP=5\taugustus\n";
 static const CHAR ci2_feature_comp_dat[] = "Feature_\tComponent_\n"
                                            "s38\ts72\n"
@@ -656,13 +632,6 @@
                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
                                         "Component\tComponent\n"
                                         "augustus\t\tMSITESTDIR\t0\tMYPROP=2718 and
MyProp=42\taugustus\n";
-
-static const CHAR rem_file_dat[] =
"File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
-                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
-                                   "File\tFile\n"
-
"hydrogen\thydrogen\thydrogen\t0\t\t\t8192\t1\n"
-                                   "helium\thelium\thelium\t0\t\t\t8192\t1\n"
-                                   "lithium\tlithium\tlithium\t0\t\t\t8192\t1";
 static const CHAR rem_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
                                                "s72\tS255\tI2\n"
@@ -1538,31 +1507,6 @@
     ADD_TABLE(cie_file),
     ADD_TABLE(install_exec_seq),
     ADD_TABLE(cie_media),
-    ADD_TABLE(property),
-};
-
-static const msi_table ci_tables[] =
-{
-    ADD_TABLE(ci_component),
-    ADD_TABLE(directory),
-    ADD_TABLE(rof_feature),
-    ADD_TABLE(rof_feature_comp),
-    ADD_TABLE(rof_file),
-    ADD_TABLE(ci_install_exec_seq),
-    ADD_TABLE(rof_media),
-    ADD_TABLE(property),
-    ADD_TABLE(ci_custom_action),
-};
-
-static const msi_table ci2_tables[] =
-{
-    ADD_TABLE(ci2_component),
-    ADD_TABLE(directory),
-    ADD_TABLE(rof_feature),
-    ADD_TABLE(ci2_feature_comp),
-    ADD_TABLE(ci2_file),
-    ADD_TABLE(install_exec_seq),
-    ADD_TABLE(rof_media),
     ADD_TABLE(property),
 };
@@ -5723,7 +5667,7 @@
     res = RegOpenKeyExA(HKEY_CLASSES_ROOT,
"CLSID\\{8dfef911-6885-41eb-b280-8f0304728e8b}\\InProcServer32",
                         0, KEY_ALL_ACCESS|KEY_WOW64_32KEY, &hkey);
-    todo_wine ok(res == ERROR_SUCCESS, "can't open 32-bit CLSID key, got
%d\n", res);
+    ok(res == ERROR_SUCCESS, "can't open 32-bit CLSID key, got %d\n", res);
     if (res == ERROR_SUCCESS) {
         size = sizeof(value);
         res = RegQueryValueExA(hkey, "", NULL, NULL, (LPBYTE)value, &size);
@@ -5786,7 +5730,7 @@
     res = RegOpenKeyExA(HKEY_CLASSES_ROOT,
"CLSID\\{8dfef911-6885-41eb-b280-8f0304728e8b}\\InProcServer32",
                         0, KEY_ALL_ACCESS|KEY_WOW64_32KEY, &hkey);
-    todo_wine ok(res == ERROR_SUCCESS, "can't open 32-bit CLSID key, got
%d\n", res);
+    ok(res == ERROR_SUCCESS, "can't open 32-bit CLSID key, got %d\n", res);
     if (res == ERROR_SUCCESS) {
         size = sizeof(value);
         res = RegQueryValueExA(hkey, "", NULL, NULL, (LPBYTE)value, &size);
Modified: trunk/rostests/winetests/msi/msi.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/msi/msi.c?rev=6…
==============================================================================
--- trunk/rostests/winetests/msi/msi.c  [iso-8859-1] (original)
+++ trunk/rostests/winetests/msi/msi.c  [iso-8859-1] Mon Mar  9 20:28:54 2015
@@ -48,6 +48,10 @@
 static INSTALLSTATE (WINAPI *pMsiGetComponentPathA)
     (LPCSTR, LPCSTR, LPSTR, DWORD*);
+static INSTALLSTATE (WINAPI *pMsiProvideComponentA)
+    (LPCSTR, LPCSTR, LPCSTR, DWORD, LPSTR, LPDWORD);
+static INSTALLSTATE (WINAPI *pMsiProvideComponentW)
+    (LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPWSTR, LPDWORD);
 static UINT (WINAPI *pMsiGetFileHashA)
     (LPCSTR, DWORD, PMSIFILEHASHINFO);
 static UINT (WINAPI *pMsiGetProductInfoExA)
@@ -86,6 +90,8 @@
       trace("GetProcAddress(%s) failed\n", #func);
     GET_PROC(hmsi, MsiGetComponentPathA)
+    GET_PROC(hmsi, MsiProvideComponentA)
+    GET_PROC(hmsi, MsiProvideComponentW)
     GET_PROC(hmsi, MsiGetFileHashA)
     GET_PROC(hmsi, MsiGetProductInfoExA)
     GET_PROC(hmsi, MsiOpenPackageExA)
@@ -3402,6 +3408,100 @@
     LocalFree(usersid);
 }
+static void test_MsiProvideComponent(void)
+{
+    static const WCHAR sourcedirW[] =
+
{'s','o','u','r','c','e','d','i','r',0};
+    static const WCHAR productW[] =
+
{'{','3','8','8','4','7','3','3','8','-','1','B','B','C','-','4','1','0','4','-',
+
'8','1','A','C','-','2','F','A','A','C','7','E','C','D','D','C','D','}',0};
+    static const WCHAR componentW[] =
+
{'{','D','D','4','2','2','F','9','2','-','3','E','D','8','-','4','9','B','5','-',
+
'A','0','B','7','-','F','2','6','6','F','9','8','3','5','7','D','F','}',0};
+    INSTALLSTATE state;
+    char buf[0x100];
+    WCHAR bufW[0x100];
+    DWORD len, len2;
+    UINT r;
+
+    if (is_process_limited())
+    {
+        skip("process is limited\n");
+        return;
+    }
+
+    create_test_files();
+    create_file("msitest\\sourcedir.txt", "msitest\\sourcedir.txt",
1000);
+    create_database(msifile, sd_tables, sizeof(sd_tables) / sizeof(msi_table));
+
+    MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
+
+    buf[0] = 0;
+    len = sizeof(buf);
+    r = pMsiProvideComponentA("{90120000-0070-0000-0000-4000000FF1CE}",
+                              "{17961602-C4E2-482E-800A-DF6E627549CF}",
+                              "ProductFiles", INSTALLMODE_NODETECTION, buf,
&len);
+    ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
+
+    r = MsiInstallProductA(msifile, NULL);
+    ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
+
+    state = MsiQueryFeatureStateA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
"sourcedir");
+    ok(state == INSTALLSTATE_LOCAL, "got %d\n", state);
+
+    buf[0] = 0;
+    len = sizeof(buf);
+    r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
"sourcedir",
+                              "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
+                              INSTALLMODE_NODETECTION, buf, &len);
+    ok(r == ERROR_SUCCESS, "got %u\n", r);
+    ok(buf[0], "empty path\n");
+    ok(len == lstrlenA(buf), "got %u\n", len);
+
+    len2 = 0;
+    r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
"sourcedir",
+                              "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
+                              INSTALLMODE_NODETECTION, NULL, &len2);
+    ok(r == ERROR_SUCCESS, "got %u\n", r);
+    ok(len2 == len, "got %u\n", len2);
+
+    len2 = 0;
+    r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
"sourcedir",
+                              "{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
+                              INSTALLMODE_NODETECTION, buf, &len2);
+    ok(r == ERROR_MORE_DATA, "got %u\n", r);
+    ok(len2 == len, "got %u\n", len2);
+
+    /* wide version */
+
+    bufW[0] = 0;
+    len = sizeof(buf);
+    r = pMsiProvideComponentW(productW, sourcedirW, componentW,
+                              INSTALLMODE_NODETECTION, bufW, &len);
+    ok(r == ERROR_SUCCESS, "got %u\n", r);
+    ok(bufW[0], "empty path\n");
+    ok(len == lstrlenW(bufW), "got %u\n", len);
+
+    len2 = 0;
+    r = pMsiProvideComponentW(productW, sourcedirW, componentW,
+                              INSTALLMODE_NODETECTION, NULL, &len2);
+    ok(r == ERROR_SUCCESS, "got %u\n", r);
+    ok(len2 == len, "got %u\n", len2);
+
+    len2 = 0;
+    r = pMsiProvideComponentW(productW, sourcedirW, componentW,
+                              INSTALLMODE_NODETECTION, bufW, &len2);
+    ok(r == ERROR_MORE_DATA, "got %u\n", r);
+    ok(len2 == len, "got %u\n", len2);
+
+    r = MsiInstallProductA(msifile, "REMOVE=ALL");
+    ok(r == ERROR_SUCCESS, "got %u\n", r);
+
+    DeleteFileA("msitest\\sourcedir.txt");
+    delete_test_files();
+    DeleteFileA(msifile);
+}
+
 static void test_MsiGetProductCode(void)
 {
     HKEY compkey, prodkey;
@@ -14298,6 +14398,7 @@
         test_MsiQueryFeatureState();
         test_MsiQueryComponentState();
         test_MsiGetComponentPath();
+        test_MsiProvideComponent();
         test_MsiGetProductCode();
         test_MsiEnumClients();
         test_MsiGetProductInfo();
Modified: trunk/rostests/winetests/msi/package.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/msi/package.c?r…
==============================================================================
--- trunk/rostests/winetests/msi/package.c      [iso-8859-1] (original)
+++ trunk/rostests/winetests/msi/package.c      [iso-8859-1] Mon Mar  9 20:28:54 2015
@@ -2194,7 +2194,7 @@
     sz = 6;
     r = MsiGetPropertyA(hpkg, "property", buffer, &sz);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
-    ok( !strlen(buffer), "Expected empty string, got %s\n", buffer);
+    ok(!buffer[0], "Expected empty string, got %s\n", buffer);
     MsiCloseHandle( hpkg );
     DeleteFileA(msifile);
@@ -2347,7 +2347,7 @@
     lstrcpyA(buffer, "aaa");
     r = MsiGetPropertyA(hpkg, "dantes", buffer, &sz);
     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
-    ok(lstrlenA(buffer) == 0, "Expected empty string, got %s\n", buffer);
+    ok(!buffer[0], "Expected empty string, got %s\n", buffer);
     r = MsiSetPropertyA(hpkg, "dantes", "mercedes");
     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
Modified: trunk/rostests/winetests/msi/source.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/msi/source.c?re…
==============================================================================
--- trunk/rostests/winetests/msi/source.c       [iso-8859-1] (original)
+++ trunk/rostests/winetests/msi/source.c       [iso-8859-1] Mon Mar  9 20:28:54 2015
@@ -175,7 +175,7 @@
     }
     if (!expected)
-        ok_(__FILE__, line)(lstrlenA(val) == 0, "Expected empty string, got
%s\n", val);
+        ok_(__FILE__, line)(!val[0], "Expected empty string, got %s\n", val);
     else
     {
         if (bcase)