Author: cwittich Date: Mon Oct 19 23:11:46 2009 New Revision: 43625
URL: http://svn.reactos.org/svn/reactos?rev=43625&view=rev Log: -sync msi_winetest with wine 1.1.31
Modified: trunk/rostests/winetests/msi/automation.c trunk/rostests/winetests/msi/install.c trunk/rostests/winetests/msi/msi.c trunk/rostests/winetests/msi/package.c trunk/rostests/winetests/msi/suminfo.c
Modified: trunk/rostests/winetests/msi/automation.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/msi/automation.c... ============================================================================== --- trunk/rostests/winetests/msi/automation.c [iso-8859-1] (original) +++ trunk/rostests/winetests/msi/automation.c [iso-8859-1] Mon Oct 19 23:11:46 2009 @@ -369,8 +369,8 @@ { CHAR str1A[MAX_PATH], str2A[MAX_PATH];
- WideCharToMultiByte(CP_ACP, 0, str1, -1, str1A, MAX_PATH, NULL, NULL); \ - WideCharToMultiByte(CP_ACP, 0, str2, -1, str2A, MAX_PATH, NULL, NULL); \ + WideCharToMultiByte(CP_ACP, 0, str1, -1, str1A, MAX_PATH, NULL, NULL); + WideCharToMultiByte(CP_ACP, 0, str2, -1, str2A, MAX_PATH, NULL, NULL);
return lstrcmpA(str1A, str2A); }
Modified: trunk/rostests/winetests/msi/install.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/msi/install.c?re... ============================================================================== --- trunk/rostests/winetests/msi/install.c [iso-8859-1] (original) +++ trunk/rostests/winetests/msi/install.c [iso-8859-1] Mon Oct 19 23:11:46 2009 @@ -124,6 +124,8 @@ "MoveFiles\t\t1700\n" "InstallFiles\t\t4000\n" "DuplicateFiles\t\t4500\n" + "WriteEnvironmentStrings\t\t4550\n" + "CreateShortcuts\t\t4600\n" "InstallServices\t\t5000\n" "InstallFinalize\t\t6600\n" "InstallInitialize\t\t1500\n" @@ -158,6 +160,24 @@ "ROOTDRIVE\tC:\\n" "SERVNAME\tTestService\n" "SERVDISP\tTestServiceDisp\n"; + +static const CHAR shortcut_dat[] = "Shortcut\tDirectory_\tName\tComponent_\tTarget\tArguments\tDescription\tHotkey\tIcon_\tIconIndex\tShowCmd\tWkDir\n" + "s72\ts72\tl128\ts72\ts72\tS255\tL255\tI2\tS72\tI2\tI2\tS72\n" + "Shortcut\tShortcut\n" + "Shortcut\tMSITESTDIR\tShortcut\tcomponent\tShortcut\t\tShortcut\t\t\t\t\t\n"; + +static const CHAR environment_dat[] = "Environment\tName\tValue\tComponent_\n" + "s72\tl255\tL255\ts72\n" + "Environment\tEnvironment\n" + "Var1\t=-MSITESTVAR1\t1\tOne\n" + "Var2\tMSITESTVAR2\t1\tOne\n" + "Var3\t=-MSITESTVAR3\t1\tOne\n" + "Var4\tMSITESTVAR4\t1\tOne\n"; + +static const CHAR condition_dat[] = "Feature_\tLevel\tCondition\n" + "s38\ti2\tS255\n" + "Condition\tFeature_\tLevel\n" + "One\t4\t1\n";
static const CHAR up_property_dat[] = "Property\tValue\n" "s72\tl0\n" @@ -381,6 +401,21 @@ "Media\tDiskId\n" "1\t1\t\t\tDISK1\t\n";
+static const CHAR rofc_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n" + "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n" + "File\tFile\n" + "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1"; + +static const CHAR rofc_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n" + "i2\ti4\tL64\tS255\tS32\tS72\n" + "Media\tDiskId\n" + "1\t1\t\ttest1.cab\tDISK1\t\n"; + +static const CHAR lus2_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n" + "i2\ti4\tL64\tS255\tS32\tS72\n" + "Media\tDiskId\n" + "1\t1\t\t#test1.cab\tDISK1\t\n"; + static const CHAR sdp_install_exec_seq_dat[] = "Action\tCondition\tSequence\n" "s72\tS255\tI2\n" "InstallExecuteSequence\tAction\n" @@ -851,6 +886,32 @@ "file\tcomponent\tfilename\t100\t\t\t8192\t1\n" "service_file\tservice_comp\tservice.exe\t100\t\t\t8192\t1";
+static const CHAR ip_install_exec_seq_dat[] = "Action\tCondition\tSequence\n" + "s72\tS255\tI2\n" + "InstallExecuteSequence\tAction\n" + "CostFinalize\t\t1000\n" + "ValidateProductID\t\t700\n" + "CostInitialize\t\t800\n" + "FileCost\t\t900\n" + "RemoveFiles\t\t3500\n" + "InstallFiles\t\t4000\n" + "RegisterUser\t\t6000\n" + "RegisterProduct\t\t6100\n" + "PublishFeatures\t\t6300\n" + "PublishProduct\t\t6400\n" + "InstallFinalize\t\t6600\n" + "InstallInitialize\t\t1500\n" + "ProcessComponents\t\t1600\n" + "UnpublishFeatures\t\t1800\n" + "InstallValidate\t\t1400\n" + "LaunchConditions\t\t100\n" + "TestInstalledProp\tInstalled AND NOT REMOVE\t950\n"; + +static const CHAR ip_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n" + "s72\ti2\tS64\tS0\tS255\n" + "CustomAction\tAction\n" + "TestInstalledProp\t19\t\tTest failed\t\n"; + typedef struct _msi_table { const CHAR *filename; @@ -875,6 +936,45 @@ ADD_TABLE(service_control) };
+static const msi_table sc_tables[] = +{ + ADD_TABLE(component), + ADD_TABLE(directory), + ADD_TABLE(feature), + ADD_TABLE(feature_comp), + ADD_TABLE(file), + ADD_TABLE(install_exec_seq), + ADD_TABLE(media), + ADD_TABLE(property), + ADD_TABLE(shortcut) +}; + +static const msi_table ps_tables[] = +{ + ADD_TABLE(component), + ADD_TABLE(directory), + ADD_TABLE(feature), + ADD_TABLE(feature_comp), + ADD_TABLE(file), + ADD_TABLE(install_exec_seq), + ADD_TABLE(media), + ADD_TABLE(property), + ADD_TABLE(condition) +}; + +static const msi_table env_tables[] = +{ + ADD_TABLE(component), + ADD_TABLE(directory), + ADD_TABLE(feature), + ADD_TABLE(feature_comp), + ADD_TABLE(file), + ADD_TABLE(install_exec_seq), + ADD_TABLE(media), + ADD_TABLE(property), + ADD_TABLE(environment) +}; + static const msi_table up_tables[] = { ADD_TABLE(component), @@ -1078,6 +1178,18 @@ ADD_TABLE(property), };
+static const msi_table rofc_tables[] = +{ + ADD_TABLE(rof_component), + ADD_TABLE(directory), + ADD_TABLE(rof_feature), + ADD_TABLE(rof_feature_comp), + ADD_TABLE(rofc_file), + ADD_TABLE(install_exec_seq), + ADD_TABLE(rofc_media), + ADD_TABLE(property), +}; + static const msi_table sdp_tables[] = { ADD_TABLE(rof_component), @@ -1166,6 +1278,42 @@ ADD_TABLE(property), };
+static const msi_table lus0_tables[] = +{ + ADD_TABLE(ci_component), + ADD_TABLE(directory), + ADD_TABLE(rof_feature), + ADD_TABLE(rof_feature_comp), + ADD_TABLE(rof_file), + ADD_TABLE(pp_install_exec_seq), + ADD_TABLE(rof_media), + ADD_TABLE(property), +}; + +static const msi_table lus1_tables[] = +{ + ADD_TABLE(ci_component), + ADD_TABLE(directory), + ADD_TABLE(rof_feature), + ADD_TABLE(rof_feature_comp), + ADD_TABLE(rof_file), + ADD_TABLE(pp_install_exec_seq), + ADD_TABLE(rofc_media), + ADD_TABLE(property), +}; + +static const msi_table lus2_tables[] = +{ + ADD_TABLE(ci_component), + ADD_TABLE(directory), + ADD_TABLE(rof_feature), + ADD_TABLE(rof_feature_comp), + ADD_TABLE(rof_file), + ADD_TABLE(pp_install_exec_seq), + ADD_TABLE(lus2_media), + ADD_TABLE(property), +}; + static const msi_table tp_tables[] = { ADD_TABLE(tp_component), @@ -1376,6 +1524,43 @@ ADD_TABLE(install_exec_seq), ADD_TABLE(rof_media), ADD_TABLE(property) +}; + +static const msi_table ip_tables[] = +{ + ADD_TABLE(component), + ADD_TABLE(directory), + ADD_TABLE(feature), + ADD_TABLE(feature_comp), + ADD_TABLE(file), + ADD_TABLE(ip_install_exec_seq), + ADD_TABLE(ip_custom_action), + ADD_TABLE(media), + ADD_TABLE(property) +}; + +static const msi_table fiu_tables[] = +{ + ADD_TABLE(rof_component), + ADD_TABLE(directory), + ADD_TABLE(rof_feature), + ADD_TABLE(rof_feature_comp), + ADD_TABLE(rof_file), + ADD_TABLE(pp_install_exec_seq), + ADD_TABLE(rof_media), + ADD_TABLE(property), +}; + +static const msi_table fiuc_tables[] = +{ + ADD_TABLE(rof_component), + ADD_TABLE(directory), + ADD_TABLE(rof_feature), + ADD_TABLE(rof_feature_comp), + ADD_TABLE(rofc_file), + ADD_TABLE(pp_install_exec_seq), + ADD_TABLE(rofc_media), + ADD_TABLE(property), };
/* cabinet definitions */ @@ -2576,6 +2761,219 @@ DeleteFile("msitest\maximus"); RemoveDirectory("msitest"); DeleteFile(msifile); +} + +static void test_readonlyfile_cab(void) +{ + UINT r; + DWORD size; + HANDLE file; + CHAR path[MAX_PATH]; + CHAR buf[16]; + + CreateDirectoryA("msitest", NULL); + create_file("maximus", 500); + create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0"); + DeleteFile("maximus"); + + create_database(msifile, rofc_tables, sizeof(rofc_tables) / sizeof(msi_table)); + + MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL); + + lstrcpy(path, PROG_FILES_DIR); + lstrcat(path, "\msitest"); + CreateDirectory(path, NULL); + + lstrcat(path, "\maximus"); + file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, CREATE_NEW, FILE_ATTRIBUTE_READONLY, NULL); + + WriteFile(file, "readonlyfile", strlen("readonlyfile"), &size, NULL); + CloseHandle(file); + + r = MsiInstallProductA(msifile, NULL); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + memset( buf, 0, sizeof(buf) ); + if ((file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE) + { + ReadFile(file, buf, sizeof(buf) - 1, &size, NULL); + CloseHandle(file); + } + ok( !lstrcmp( buf, "maximus" ), "Expected file to be overwritten, got '%s'\n", buf ); + ok(delete_pf("msitest\maximus", TRUE), "File not installed\n"); + ok(delete_pf("msitest", FALSE), "File not installed\n"); + + /* Delete the files in the temp (current) folder */ + delete_cab_files(); + DeleteFile("msitest\maximus"); + RemoveDirectory("msitest"); + DeleteFile(msifile); +} + +static BOOL add_cabinet_storage(LPCSTR db, LPCSTR cabinet) +{ + WCHAR dbW[MAX_PATH], cabinetW[MAX_PATH]; + IStorage *stg; + IStream *stm; + HRESULT hr; + HANDLE handle; + + MultiByteToWideChar(CP_ACP, 0, db, -1, dbW, MAX_PATH); + hr = StgOpenStorage(dbW, NULL, STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL, 0, &stg); + if (FAILED(hr)) + return FALSE; + + MultiByteToWideChar(CP_ACP, 0, cabinet, -1, cabinetW, MAX_PATH); + hr = IStorage_CreateStream(stg, cabinetW, STGM_WRITE|STGM_SHARE_EXCLUSIVE, 0, 0, &stm); + if (FAILED(hr)) + { + IStorage_Release(stg); + return FALSE; + } + + handle = CreateFileW(cabinetW, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); + if (handle != INVALID_HANDLE_VALUE) + { + DWORD count; + char buffer[1024]; + if (ReadFile(handle, buffer, sizeof(buffer), &count, NULL)) + IStream_Write(stm, buffer, count, &count); + CloseHandle(handle); + } + + IStream_Release(stm); + IStorage_Release(stg); + + return TRUE; +} + +static void test_lastusedsource(void) +{ + static char prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}"; + + UINT r; + char value[MAX_PATH], path[MAX_PATH]; + DWORD size; + + if (!pMsiSourceListGetInfoA) + { + win_skip("MsiSourceListGetInfoA is not available\n"); + return; + } + + CreateDirectoryA("msitest", NULL); + create_file("maximus", 500); + create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0"); + DeleteFile("maximus"); + + create_database("msifile0.msi", lus0_tables, sizeof(lus0_tables) / sizeof(msi_table)); + create_database("msifile1.msi", lus1_tables, sizeof(lus1_tables) / sizeof(msi_table)); + create_database("msifile2.msi", lus2_tables, sizeof(lus2_tables) / sizeof(msi_table)); + + MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL); + + /* no cabinet file */ + + size = MAX_PATH; + lstrcpyA(value, "aaa"); + r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, + MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE, value, &size); + ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r); + ok(!lstrcmpA(value, "aaa"), "Expected "aaa", got "%s"\n", value); + + r = MsiInstallProductA("msifile0.msi", "PUBLISH_PRODUCT=1"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + lstrcpyA(path, CURR_DIR); + lstrcatA(path, "\"); + + size = MAX_PATH; + lstrcpyA(value, "aaa"); + r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, + MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE, value, &size); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + todo_wine + { + ok(!lstrcmpA(value, path), "Expected "%s", got "%s"\n", path, value); + ok(size == lstrlenA(path), "Expected %d, got %d\n", lstrlenA(path), size); + } + + r = MsiInstallProductA("msifile0.msi", "REMOVE=ALL"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + /* separate cabinet file */ + + size = MAX_PATH; + lstrcpyA(value, "aaa"); + r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, + MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE, value, &size); + ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r); + ok(!lstrcmpA(value, "aaa"), "Expected "aaa", got "%s"\n", value); + + r = MsiInstallProductA("msifile1.msi", "PUBLISH_PRODUCT=1"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + lstrcpyA(path, CURR_DIR); + lstrcatA(path, "\"); + + size = MAX_PATH; + lstrcpyA(value, "aaa"); + r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, + MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE, value, &size); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + todo_wine + { + ok(!lstrcmpA(value, path), "Expected "%s", got "%s"\n", path, value); + ok(size == lstrlenA(path), "Expected %d, got %d\n", lstrlenA(path), size); + } + + r = MsiInstallProductA("msifile1.msi", "REMOVE=ALL"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + size = MAX_PATH; + lstrcpyA(value, "aaa"); + r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, + MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE, value, &size); + ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r); + ok(!lstrcmpA(value, "aaa"), "Expected "aaa", got "%s"\n", value); + + /* embedded cabinet stream */ + + add_cabinet_storage("msifile2.msi", "test1.cab"); + + r = MsiInstallProductA("msifile2.msi", "PUBLISH_PRODUCT=1"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + size = MAX_PATH; + lstrcpyA(value, "aaa"); + r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, + MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE, value, &size); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + todo_wine + { + ok(!lstrcmpA(value, path), "Expected "%s", got "%s"\n", path, value); + ok(size == lstrlenA(path), "Expected %d, got %d\n", lstrlenA(path), size); + } + + r = MsiInstallProductA("msifile2.msi", "REMOVE=ALL"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + size = MAX_PATH; + lstrcpyA(value, "aaa"); + r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, + MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE, value, &size); + ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r); + ok(!lstrcmpA(value, "aaa"), "Expected "aaa", got "%s"\n", value); + + /* Delete the files in the temp (current) folder */ + delete_cab_files(); + DeleteFile("msitest\maximus"); + RemoveDirectory("msitest"); + DeleteFile("msifile0.msi"); + DeleteFile("msifile1.msi"); + DeleteFile("msifile2.msi"); }
static void test_setdirproperty(void) @@ -4401,10 +4799,7 @@ ok(r == ERROR_SUCCESS, "Failed to set summary info\n");
r = MsiSummaryInfoPersist(suminfo); - todo_wine - { - ok(r == ERROR_SUCCESS , "Failed to make summary info persist\n"); - } + ok(r == ERROR_SUCCESS , "Failed to make summary info persist\n");
r = MsiCloseHandle(suminfo); ok(r == ERROR_SUCCESS , "Failed to close suminfo\n"); @@ -6110,6 +6505,370 @@ RemoveDirectoryA(tmpdir); }
+static void test_shortcut(void) +{ + UINT r; + HRESULT hr; + + create_test_files(); + create_database(msifile, sc_tables, sizeof(sc_tables) / sizeof(msi_table)); + + r = MsiInstallProductA(msifile, NULL); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); + ok(SUCCEEDED(hr), "CoInitialize failed 0x%08x\n", hr); + + r = MsiInstallProductA(msifile, NULL); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + CoUninitialize(); + + hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + ok(SUCCEEDED(hr), "CoInitialize failed 0x%08x\n", hr); + + r = MsiInstallProductA(msifile, NULL); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + CoUninitialize(); + + delete_pf("msitest\cabout\new\five.txt", TRUE); + delete_pf("msitest\cabout\new", FALSE); + delete_pf("msitest\cabout\four.txt", TRUE); + delete_pf("msitest\cabout", FALSE); + delete_pf("msitest\changed\three.txt", TRUE); + delete_pf("msitest\changed", FALSE); + delete_pf("msitest\first\two.txt", TRUE); + delete_pf("msitest\first", FALSE); + delete_pf("msitest\filename", TRUE); + delete_pf("msitest\one.txt", TRUE); + delete_pf("msitest\service.exe", TRUE); + delete_pf("msitest\Shortcut.lnk", TRUE); + delete_pf("msitest", FALSE); + delete_test_files(); +} + +static void test_envvar(void) +{ + UINT r; + HKEY env; + LONG res; + DWORD type, size; + char buffer[16]; + + if (on_win9x) + { + win_skip("Environment variables are handled differently on Win9x and WinMe\n"); + return; + } + + create_test_files(); + create_database(msifile, env_tables, sizeof(env_tables) / sizeof(msi_table)); + + res = RegCreateKeyExA(HKEY_CURRENT_USER, "Environment", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &env, NULL); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + res = RegSetValueExA(env, "MSITESTVAR1", 0, REG_SZ, (const BYTE *)"0", 2); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + res = RegSetValueExA(env, "MSITESTVAR2", 0, REG_SZ, (const BYTE *)"0", 2); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + r = MsiInstallProductA(msifile, NULL); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + type = REG_NONE; + size = sizeof(buffer); + buffer[0] = 0; + res = RegQueryValueExA(env, "MSITESTVAR1", NULL, &type, (LPBYTE)buffer, &size); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + ok(type == REG_SZ, "Expected REG_SZ, got %u\n", type); + ok(!lstrcmp(buffer, "1"), "Expected "1", got %s\n", buffer); + + res = RegDeleteValueA(env, "MSITESTVAR1"); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + type = REG_NONE; + size = sizeof(buffer); + buffer[0] = 0; + res = RegQueryValueExA(env, "MSITESTVAR2", NULL, &type, (LPBYTE)buffer, &size); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + ok(type == REG_SZ, "Expected REG_SZ, got %u\n", type); + ok(!lstrcmp(buffer, "1"), "Expected "1", got %s\n", buffer); + + res = RegDeleteValueA(env, "MSITESTVAR2"); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + res = RegDeleteValueA(env, "MSITESTVAR3"); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + res = RegDeleteValueA(env, "MSITESTVAR4"); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + RegCloseKey(env); + + delete_pf("msitest\cabout\new\five.txt", TRUE); + delete_pf("msitest\cabout\new", FALSE); + delete_pf("msitest\cabout\four.txt", TRUE); + delete_pf("msitest\cabout", FALSE); + delete_pf("msitest\changed\three.txt", TRUE); + delete_pf("msitest\changed", FALSE); + delete_pf("msitest\first\two.txt", TRUE); + delete_pf("msitest\first", FALSE); + delete_pf("msitest\filename", TRUE); + delete_pf("msitest\one.txt", TRUE); + delete_pf("msitest\service.exe", TRUE); + delete_pf("msitest", FALSE); + delete_test_files(); +} + +static void test_preselected(void) +{ + UINT r; + + create_test_files(); + create_database(msifile, ps_tables, sizeof(ps_tables) / sizeof(msi_table)); + + r = MsiInstallProductA(msifile, "ADDLOCAL=One"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + ok(!delete_pf("msitest\cabout\new\five.txt", TRUE), "File installed\n"); + ok(!delete_pf("msitest\cabout\new", FALSE), "File installed\n"); + ok(!delete_pf("msitest\cabout\four.txt", TRUE), "File installed\n"); + ok(!delete_pf("msitest\cabout", FALSE), "File installed\n"); + ok(!delete_pf("msitest\changed\three.txt", TRUE), "File installed\n"); + ok(!delete_pf("msitest\changed", FALSE), "File installed\n"); + ok(!delete_pf("msitest\first\two.txt", TRUE), "File installed\n"); + ok(!delete_pf("msitest\first", FALSE), "File installed\n"); + ok(!delete_pf("msitest\filename", TRUE), "File installed\n"); + todo_wine ok(delete_pf("msitest\one.txt", TRUE), "File not installed\n"); + ok(!delete_pf("msitest\service.exe", TRUE), "File installed\n"); + todo_wine ok(delete_pf("msitest", FALSE), "File not installed\n"); + + r = MsiInstallProductA(msifile, NULL); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + ok(delete_pf("msitest\cabout\new\five.txt", TRUE), "File not installed\n"); + ok(delete_pf("msitest\cabout\new", FALSE), "File not installed\n"); + ok(delete_pf("msitest\cabout\four.txt", TRUE), "File not installed\n"); + ok(delete_pf("msitest\cabout", FALSE), "File not installed\n"); + ok(delete_pf("msitest\changed\three.txt", TRUE), "File not installed\n"); + ok(delete_pf("msitest\changed", FALSE), "File not installed\n"); + ok(delete_pf("msitest\first\two.txt", TRUE), "File not installed\n"); + ok(delete_pf("msitest\first", FALSE), "File not installed\n"); + ok(delete_pf("msitest\filename", TRUE), "File not installed\n"); + ok(!delete_pf("msitest\one.txt", TRUE), "File installed\n"); + ok(delete_pf("msitest\service.exe", TRUE), "File not installed\n"); + ok(delete_pf("msitest", FALSE), "File not installed\n"); + delete_test_files(); +} + +static void test_installed_prop(void) +{ + static char prodcode[] = "{7df88a48-996f-4ec8-a022-bf956f9b2cbb}"; + UINT r; + + create_test_files(); + create_database(msifile, ip_tables, sizeof(ip_tables) / sizeof(msi_table)); + + MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL); + + r = MsiInstallProductA(msifile, "FULL=1"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + r = MsiInstallProductA(msifile, "FULL=1"); + ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r); + + r = MsiConfigureProductExA(prodcode, INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, "FULL=1"); + ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r); + + ok(delete_pf("msitest\cabout\new\five.txt", TRUE), "File not installed\n"); + ok(delete_pf("msitest\cabout\new", FALSE), "File not installed\n"); + ok(delete_pf("msitest\cabout\four.txt", TRUE), "File not installed\n"); + ok(delete_pf("msitest\cabout", FALSE), "File not installed\n"); + ok(delete_pf("msitest\changed\three.txt", TRUE), "File not installed\n"); + ok(delete_pf("msitest\changed", FALSE), "File not installed\n"); + ok(delete_pf("msitest\first\two.txt", TRUE), "File not installed\n"); + ok(delete_pf("msitest\first", FALSE), "File not installed\n"); + ok(delete_pf("msitest\filename", TRUE), "File not installed\n"); + ok(delete_pf("msitest\one.txt", TRUE), "File installed\n"); + ok(delete_pf("msitest\service.exe", TRUE), "File not installed\n"); + ok(delete_pf("msitest", FALSE), "File not installed\n"); + + r = MsiInstallProductA(msifile, "REMOVE=ALL"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + delete_test_files(); +} + +static char session_manager[] = "System\CurrentControlSet\Control\Session Manager"; +static char rename_ops[] = "PendingFileRenameOperations"; + +static void process_pending_renames(HKEY hkey) +{ + char *buf, *src, *dst; + DWORD size; + LONG ret; + + ret = RegQueryValueExA(hkey, rename_ops, NULL, NULL, NULL, &size); + buf = HeapAlloc(GetProcessHeap(), 0, size); + buf[0] = 0; + + ret = RegQueryValueExA(hkey, rename_ops, NULL, NULL, (LPBYTE)buf, &size); + ok(!ret, "RegQueryValueExA failed %d (%u)\n", ret, GetLastError()); + ok(strstr(buf, "msitest\maximus") != NULL, "Unexpected value "%s"\n", buf); + + for (src = buf; *src; src = dst + strlen(dst) + 1) + { + DWORD flags = MOVEFILE_COPY_ALLOWED; + + dst = src + strlen(src) + 1; + if (*dst == '!') + { + flags |= MOVEFILE_REPLACE_EXISTING; + dst++; + } + if (src[0] == '\' && src[1] == '?' && src[2] == '?' && src[3] == '\') src += 4; + if (*dst) + { + if (dst[0] == '\' && dst[1] == '?' && dst[2] == '?' && dst[3] == '\') dst += 4; + ok(MoveFileExA(src, dst, flags), "Failed to move file %s -> %s (%u)\n", src, dst, GetLastError()); + } + else + ok(DeleteFileA(src), "Failed to delete file %s (%u)\n", src, GetLastError()); + } + HeapFree(GetProcessHeap(), 0, buf); + RegDeleteValueA(hkey, rename_ops); +} + +static BOOL file_matches_data(LPCSTR file, LPCSTR data) +{ + DWORD len, data_len = strlen(data); + HANDLE handle; + char buf[128]; + + handle = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + ok(handle != INVALID_HANDLE_VALUE, "failed to open %s (%u)\n", file, GetLastError()); + + if (ReadFile(handle, buf, sizeof(buf), &len, NULL) && len >= data_len) + { + CloseHandle(handle); + return !memcmp(buf, data, data_len); + } + CloseHandle(handle); + return FALSE; +} + +static void test_file_in_use(void) +{ + UINT r; + DWORD size; + HANDLE file; + HKEY hkey; + char path[MAX_PATH]; + + if (on_win9x) + { + win_skip("Pending file renaming is implemented differently on Win9x and WinMe\n"); + return; + } + + RegOpenKeyExA(HKEY_LOCAL_MACHINE, session_manager, 0, KEY_ALL_ACCESS, &hkey); + if (!RegQueryValueExA(hkey, rename_ops, NULL, NULL, NULL, &size)) + { + skip("Pending file rename operations, skipping test\n"); + return; + } + + CreateDirectoryA("msitest", NULL); + create_file("msitest\maximus", 500); + create_database(msifile, fiu_tables, sizeof(fiu_tables) / sizeof(msi_table)); + + MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL); + + lstrcpy(path, PROG_FILES_DIR); + lstrcat(path, "\msitest"); + CreateDirectoryA(path, NULL); + + lstrcat(path, "\maximus"); + file = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); + + r = MsiInstallProductA(msifile, "REBOOT=ReallySuppress FULL=1"); + ok(r == ERROR_SUCCESS_REBOOT_REQUIRED, "Expected ERROR_SUCCESS_REBOOT_REQUIRED got %u\n", r); + ok(!file_matches_data(path, "msitest\maximus"), "Expected file not to match\n"); + CloseHandle(file); + ok(!file_matches_data(path, "msitest\maximus"), "Expected file not to match\n"); + + process_pending_renames(hkey); + RegCloseKey(hkey); + + ok(file_matches_data(path, "msitest\maximus"), "Expected file to match\n"); + ok(delete_pf("msitest\maximus", TRUE), "File not present\n"); + ok(delete_pf("msitest", FALSE), "Directory not present or not empty\n"); + + r = MsiInstallProductA(msifile, "REMOVE=ALL"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + delete_test_files(); +} + +static void test_file_in_use_cab(void) +{ + UINT r; + DWORD size; + HANDLE file; + HKEY hkey; + char path[MAX_PATH]; + + if (on_win9x) + { + win_skip("Pending file renaming is implemented differently on Win9x and WinMe\n"); + return; + } + + RegOpenKeyExA(HKEY_LOCAL_MACHINE, session_manager, 0, KEY_ALL_ACCESS, &hkey); + if (!RegQueryValueExA(hkey, rename_ops, NULL, NULL, NULL, &size)) + { + skip("Pending file rename operations, skipping test\n"); + return; + } + + CreateDirectoryA("msitest", NULL); + create_file("maximus", 500); + create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0"); + DeleteFile("maximus"); + + create_database(msifile, fiuc_tables, sizeof(fiuc_tables) / sizeof(msi_table)); + + MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL); + + lstrcpy(path, PROG_FILES_DIR); + lstrcat(path, "\msitest"); + CreateDirectoryA(path, NULL); + + lstrcat(path, "\maximus"); + file = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); + + r = MsiInstallProductA(msifile, "REBOOT=ReallySuppress FULL=1"); + ok(r == ERROR_SUCCESS_REBOOT_REQUIRED, "Expected ERROR_SUCCESS_REBOOT_REQUIRED got %u\n", r); + ok(!file_matches_data(path, "maximus"), "Expected file not to match\n"); + CloseHandle(file); + ok(!file_matches_data(path, "maximus"), "Expected file not to match\n"); + + process_pending_renames(hkey); + RegCloseKey(hkey); + + ok(file_matches_data(path, "maximus"), "Expected file to match\n"); + ok(delete_pf("msitest\maximus", TRUE), "File not present\n"); + ok(delete_pf("msitest", FALSE), "Directory not present or not empty\n"); + + r = MsiInstallProductA(msifile, "REMOVE=ALL"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + delete_cab_files(); + delete_test_files(); +} + START_TEST(install) { DWORD len; @@ -6160,6 +6919,7 @@ test_samesequence(); test_uiLevelFlags(); test_readonlyfile(); + test_readonlyfile_cab(); test_setdirproperty(); test_cabisextracted(); test_concurrentinstall(); @@ -6190,6 +6950,13 @@ test_adminimage(); test_propcase(); test_int_widths(); + test_shortcut(); + test_envvar(); + test_lastusedsource(); + test_preselected(); + test_installed_prop(); + test_file_in_use(); + test_file_in_use_cab();
DeleteFileA(log_file);
Modified: trunk/rostests/winetests/msi/msi.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/msi/msi.c?rev=43... ============================================================================== --- trunk/rostests/winetests/msi/msi.c [iso-8859-1] (original) +++ trunk/rostests/winetests/msi/msi.c [iso-8859-1] Mon Oct 19 23:11:46 2009 @@ -8510,7 +8510,7 @@ RegCloseKey(prodkey); }
-static void test_MsiEnumPatchesEx_machine() +static void test_MsiEnumPatchesEx_machine(void) { CHAR keypath[MAX_PATH], patch[MAX_PATH]; CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
Modified: trunk/rostests/winetests/msi/package.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/msi/package.c?re... ============================================================================== --- trunk/rostests/winetests/msi/package.c [iso-8859-1] (original) +++ trunk/rostests/winetests/msi/package.c [iso-8859-1] Mon Oct 19 23:11:46 2009 @@ -26,6 +26,7 @@ #include <msidefs.h> #include <msi.h> #include <msiquery.h> +#include <srrestoreptapi.h>
#include "wine/test.h"
@@ -35,11 +36,15 @@ static UINT (WINAPI *pMsiApplyMultiplePatchesA)(LPCSTR, LPCSTR, LPCSTR);
static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*); + +static BOOL (WINAPI *pSRRemoveRestorePoint)(DWORD); +static BOOL (WINAPI *pSRSetRestorePointA)(RESTOREPOINTINFOA*, STATEMGRSTATUS*);
static void init_functionpointers(void) { HMODULE hmsi = GetModuleHandleA("msi.dll"); HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll"); + HMODULE hsrclient;
#define GET_PROC(mod, func) \ p ## func = (void*)GetProcAddress(mod, #func); @@ -48,6 +53,9 @@
GET_PROC(hadvapi32, ConvertSidToStringSidA);
+ hsrclient = LoadLibraryA("srclient.dll"); + GET_PROC(hsrclient, SRRemoveRestorePoint); + GET_PROC(hsrclient, SRSetRestorePointA); #undef GET_PROC }
@@ -738,7 +746,8 @@ BOOL ret = FALSE;
GetSystemDirectory(path, MAX_PATH); - lstrcatA(path, "\kernel32.dll"); + /* Some dlls can't be updated on Vista/W2K8 */ + lstrcatA(path, "\version.dll");
CopyFileA(path, name, FALSE);
@@ -772,6 +781,27 @@ done: HeapFree(GetProcessHeap(), 0, buffer); return ret; +} + +static BOOL notify_system_change(DWORD event_type, STATEMGRSTATUS *status) +{ + RESTOREPOINTINFOA spec; + + spec.dwEventType = event_type; + spec.dwRestorePtType = APPLICATION_INSTALL; + spec.llSequenceNumber = status->llSequenceNumber; + lstrcpyA(spec.szDescription, "msitest restore point"); + + return pSRSetRestorePointA(&spec, status); +} + +static void remove_restore_point(DWORD seq_number) +{ + DWORD res; + + res = pSRRemoveRestorePoint(seq_number); + if (res != ERROR_SUCCESS) + trace("Failed to remove the restore point : %08x\n", res); }
static void test_createpackage(void) @@ -11870,9 +11900,21 @@
START_TEST(package) { + STATEMGRSTATUS status; + BOOL ret = FALSE; + init_functionpointers();
GetCurrentDirectoryA(MAX_PATH, CURR_DIR); + + /* Create a restore point ourselves so we circumvent the multitude of restore points + * that would have been created by all the installation and removal tests. + */ + if (pSRSetRestorePointA) + { + memset(&status, 0, sizeof(status)); + ret = notify_system_change(BEGIN_NESTED_SYSTEM_CHANGE, &status); + }
test_createpackage(); test_doaction(); @@ -11905,4 +11947,11 @@ test_MsiSetProperty(); test_MsiApplyMultiplePatches(); test_MsiApplyPatch(); + + if (pSRSetRestorePointA && ret) + { + ret = notify_system_change(END_NESTED_SYSTEM_CHANGE, &status); + if (ret) + remove_restore_point(status.llSequenceNumber); + } }
Modified: trunk/rostests/winetests/msi/suminfo.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/msi/suminfo.c?re... ============================================================================== --- trunk/rostests/winetests/msi/suminfo.c [iso-8859-1] (original) +++ trunk/rostests/winetests/msi/suminfo.c [iso-8859-1] Mon Oct 19 23:11:46 2009 @@ -239,6 +239,32 @@ r = MsiCloseHandle(hdb); ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
+ /* filename, non-zero update count */ + MsiGetSummaryInformation(0, msifile, 1, &hsuminfo); + ok(r == ERROR_SUCCESS, "MsiGetSummaryInformation failed\n"); + + r = MsiSummaryInfoSetProperty(hsuminfo, PID_AUTHOR, VT_LPSTR, 1, &ft, "Mike"); + ok(r == ERROR_SUCCESS, "MsiSummaryInfoSetProperty wrong error\n"); + + r = MsiSummaryInfoPersist(hsuminfo); + ok(r == ERROR_SUCCESS, "MsiSummaryInfoPersist failed %u\n", r); + + r = MsiCloseHandle(hsuminfo); + ok(r == ERROR_SUCCESS, "MsiCloseHandle failed %u\n", r); + + /* filename, zero update count */ + MsiGetSummaryInformation(0, msifile, 0, &hsuminfo); + ok(r == ERROR_SUCCESS, "MsiGetSummaryInformation failed %u\n", r); + + r = MsiSummaryInfoSetProperty(hsuminfo, PID_AUTHOR, VT_LPSTR, 1, &ft, "Mike"); + todo_wine ok(r == ERROR_FUNCTION_FAILED, "MsiSummaryInfoSetProperty wrong error, %u\n", r); + + r = MsiSummaryInfoPersist(hsuminfo); + ok(r == ERROR_FUNCTION_FAILED, "MsiSummaryInfoPersist wrong error %u\n", r); + + r = MsiCloseHandle(hsuminfo); + ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); + r = DeleteFile(msifile); ok(r, "DeleteFile failed\n"); } @@ -409,6 +435,12 @@ ok(r == ERROR_SUCCESS, "getpropcount failed\n"); todo_wine ok(count == 10, "prop count incorrect\n");
+ r = MsiSummaryInfoSetProperty( hsuminfo, PID_TITLE, VT_LPSTR, 0, NULL, "Mike" ); + ok(r == ERROR_FUNCTION_FAILED, "MsiSummaryInfoSetProperty failed %u\n", r); + + r = MsiSummaryInfoPersist( hsuminfo ); + ok(r == ERROR_FUNCTION_FAILED, "MsiSummaryInfoPersist failed %u\n", r); + MsiCloseHandle( hsuminfo ); MsiCloseHandle( hdb );