Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/msi/tests/action.c | 14 ++++++++++++++ dlls/msi/tests/custom.c | 22 ++++++++++++++++++++++ dlls/msi/tests/custom.spec | 2 ++ 3 files changed, 38 insertions(+)
diff --git a/dlls/msi/tests/action.c b/dlls/msi/tests/action.c index 70baaa3..966158b 100644 --- a/dlls/msi/tests/action.c +++ b/dlls/msi/tests/action.c @@ -1081,13 +1081,26 @@ static const char rd_install_exec_seq_dat[] = "InstallInitialize\t\t1500\n" "ProcessComponents\t\t1600\n" "RemoveDuplicateFiles\t\t1900\n" + "rd_immediate\tREMOVE\t1901\n" + "rd_deferred\tREMOVE\t1902\n" "InstallFiles\t\t2000\n" "DuplicateFiles\t\t2100\n" + "df_immediate\tNOT REMOVE\t2101\n" + "df_deferred\tNOT REMOVE\t2102\n" "RegisterProduct\t\t5000\n" "PublishFeatures\t\t5100\n" "PublishProduct\t\t5200\n" "InstallFinalize\t\t6000\n";
+static const char rd_custom_action_dat[] = + "Action\tType\tSource\tTarget\n" + "s72\ti2\tS64\tS0\n" + "CustomAction\tAction\n" + "df_immediate\t1\tcustom.dll\trd_absent\n" + "df_deferred\t1025\tcustom.dll\trd_present\n" + "rd_immediate\t1\tcustom.dll\trd_present\n" + "rd_deferred\t1025\tcustom.dll\trd_absent\n"; + static const char rrv_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n" "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n" @@ -1996,6 +2009,7 @@ static const msi_table rd_tables[] = ADD_TABLE(rd_file), ADD_TABLE(rd_duplicate_file), ADD_TABLE(rd_install_exec_seq), + ADD_TABLE(rd_custom_action), ADD_TABLE(media), ADD_TABLE(property) }; diff --git a/dlls/msi/tests/custom.c b/dlls/msi/tests/custom.c index 9c9966c..9dfabf8 100644 --- a/dlls/msi/tests/custom.c +++ b/dlls/msi/tests/custom.c @@ -1274,3 +1274,25 @@ UINT WINAPI sss_stopped(MSIHANDLE hinst) CloseServiceHandle(manager); return ERROR_SUCCESS; } + +UINT WINAPI rd_present(MSIHANDLE hinst) +{ +todo_wine_if(!MsiGetMode(hinst, MSIRUNMODE_SCHEDULED)) { + ok(hinst, pf_exists("msitest\original2.txt"), "file absent\n"); + ok(hinst, pf_exists("msitest\duplicate.txt"), "file absent\n"); +} + ok(hinst, !pf_exists("msitest\original3.txt"), "file present\n"); + ok(hinst, !pf_exists("msitest\duplicate2.txt"), "file present\n"); + return ERROR_SUCCESS; +} + +UINT WINAPI rd_absent(MSIHANDLE hinst) +{ +todo_wine_if(!MsiGetMode(hinst, MSIRUNMODE_SCHEDULED)) { + ok(hinst, !pf_exists("msitest\original2.txt"), "file present\n"); + ok(hinst, !pf_exists("msitest\duplicate.txt"), "file present\n"); +} + ok(hinst, !pf_exists("msitest\original3.txt"), "file present\n"); + ok(hinst, !pf_exists("msitest\duplicate2.txt"), "file present\n"); + return ERROR_SUCCESS; +} diff --git a/dlls/msi/tests/custom.spec b/dlls/msi/tests/custom.spec index 01b95e9..10e7e9d 100644 --- a/dlls/msi/tests/custom.spec +++ b/dlls/msi/tests/custom.spec @@ -7,6 +7,8 @@ @ stdcall cf_absent(long) @ stdcall crs_present(long) @ stdcall crs_absent(long) +@ stdcall rd_present(long) +@ stdcall rd_absent(long) @ stdcall sds_present(long) @ stdcall sds_absent(long) @ stdcall sis_present(long)
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/msi/tests/action.c | 8 ++++++++ dlls/msi/tests/custom.c | 18 ++++++++++++++++++ dlls/msi/tests/custom.spec | 2 ++ 3 files changed, 28 insertions(+)
diff --git a/dlls/msi/tests/action.c b/dlls/msi/tests/action.c index 966158b..d2fad6c 100644 --- a/dlls/msi/tests/action.c +++ b/dlls/msi/tests/action.c @@ -643,6 +643,8 @@ static const char cf_install_exec_seq_dat[] = "CostInitialize\t\t800\n" "FileCost\t\t900\n" "RemoveFiles\t\t3500\n" + "rfi_immediate\tREMOVE\t3501\n" + "rfi_deferred\tREMOVE\t3502\n" "CreateFolders\t\t3700\n" "cf_immediate\tNOT REMOVE\t3701\n" "cf_deferred\tNOT REMOVE\t3702\n" @@ -650,6 +652,8 @@ static const char cf_install_exec_seq_dat[] = "rf_immediate\tREMOVE\t3801\n" "rf_deferred\tREMOVE\t3802\n" "InstallFiles\t\t4000\n" + "ifi_immediate\tNOT REMOVE\t4001\n" + "ifi_deferred\tNOT REMOVE\t4002\n" "RegisterUser\t\t6000\n" "RegisterProduct\t\t6100\n" "PublishFeatures\t\t6300\n" @@ -665,6 +669,10 @@ static const char cf_custom_action_dat[] = "Action\tType\tSource\tTarget\n" "s72\ti2\tS64\tS0\n" "CustomAction\tAction\n" + "ifi_immediate\t1\tcustom.dll\tfile_absent\n" + "ifi_deferred\t1025\tcustom.dll\tfile_present\n" + "rfi_immediate\t1\tcustom.dll\tfile_present\n" + "rfi_deferred\t1025\tcustom.dll\tfile_absent\n" "cf_immediate\t1\tcustom.dll\tcf_absent\n" "cf_deferred\t1025\tcustom.dll\tcf_present\n" "rf_immediate\t1\tcustom.dll\tcf_present\n" diff --git a/dlls/msi/tests/custom.c b/dlls/msi/tests/custom.c index 9dfabf8..8a76ef9 100644 --- a/dlls/msi/tests/custom.c +++ b/dlls/msi/tests/custom.c @@ -1180,6 +1180,24 @@ todo_wine_if(!MsiGetMode(hinst, MSIRUNMODE_SCHEDULED)) { return ERROR_SUCCESS; }
+UINT WINAPI file_present(MSIHANDLE hinst) +{ +todo_wine_if(!MsiGetMode(hinst, MSIRUNMODE_SCHEDULED)) { + ok(hinst, pf_exists("msitest\first\one.txt"), "file absent\n"); + ok(hinst, pf_exists("msitest\second\two.txt"), "file absent\n"); +} + return ERROR_SUCCESS; +} + +UINT WINAPI file_absent(MSIHANDLE hinst) +{ +todo_wine_if(!MsiGetMode(hinst, MSIRUNMODE_SCHEDULED)) { + ok(hinst, !pf_exists("msitest\first\one.txt"), "file present\n"); + ok(hinst, !pf_exists("msitest\second\two.txt"), "file present\n"); +} + return ERROR_SUCCESS; +} + UINT WINAPI crs_present(MSIHANDLE hinst) { todo_wine_if(!MsiGetMode(hinst, MSIRUNMODE_SCHEDULED)) diff --git a/dlls/msi/tests/custom.spec b/dlls/msi/tests/custom.spec index 10e7e9d..1b15ca9 100644 --- a/dlls/msi/tests/custom.spec +++ b/dlls/msi/tests/custom.spec @@ -7,6 +7,8 @@ @ stdcall cf_absent(long) @ stdcall crs_present(long) @ stdcall crs_absent(long) +@ stdcall file_present(long) +@ stdcall file_absent(long) @ stdcall rd_present(long) @ stdcall rd_absent(long) @ stdcall sds_present(long)
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check? Full results can be found at https://testbot.winehq.org/JobDetails.pl?Key=38521
Your paranoid android.
=== wxppro (32 bit install) === msi:install contains a misplaced failure message for custom
=== wvistau64_he (32 bit install) === install.c:2510: Test failed: Directory not created
=== w7pro64 (32 bit custom) === The previous 1 run(s) terminated abnormally
=== w7pro64 (64 bit custom) === The previous 1 run(s) terminated abnormally
=== w7u (32 bit msi) === The task timed out
Signed-off-by: Hans Leidekker hans@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/odbccp32/odbccp32.c | 140 +++++++++++++++++++++++------------------------ 1 file changed, 69 insertions(+), 71 deletions(-)
diff --git a/dlls/odbccp32/odbccp32.c b/dlls/odbccp32/odbccp32.c index f9a2269..8788330 100644 --- a/dlls/odbccp32/odbccp32.c +++ b/dlls/odbccp32/odbccp32.c @@ -482,99 +482,97 @@ BOOL WINAPI SQLGetConfigMode(UWORD *pwConfigMode) return TRUE; }
-/* This is implemented sensibly rather than according to exact conformance to Microsoft's buggy implementations - * e.g. The Microsoft one occasionally actually adds a third nul character (possibly beyond the buffer). - * e.g. If the key has no drivers then version 3.525.1117.0 does not modify the buffer at all, not even a nul character. - */ -BOOL WINAPI SQLGetInstalledDriversW(LPWSTR lpszBuf, WORD cbBufMax, - WORD *pcbBufOut) +BOOL WINAPI SQLGetInstalledDriversW(WCHAR *buf, WORD size, WORD *sizeout) { - HKEY hDrivers; /* Registry handle to the Drivers key */ - LONG reg_ret; /* Return code from registry functions */ - BOOL success = FALSE; /* The value we will return */ + WORD written = 0; + DWORD index = 0; + BOOL ret = TRUE; + DWORD valuelen; + WCHAR *value; + HKEY drivers; + DWORD len; + LONG res;
clear_errors();
- TRACE("%p %d %p\n", lpszBuf, cbBufMax, pcbBufOut); + TRACE("%p %d %p\n", buf, size, sizeout);
- if (!lpszBuf || cbBufMax == 0) + if (!buf || !size) { push_error(ODBC_ERROR_INVALID_BUFF_LEN, odbc_error_invalid_buff_len); + return FALSE; } - else if ((reg_ret = RegOpenKeyExW (HKEY_LOCAL_MACHINE /* The drivers does not depend on the config mode */, - drivers_key, 0, KEY_READ /* Maybe overkill */, - &hDrivers)) == ERROR_SUCCESS) + + res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, drivers_key, 0, KEY_QUERY_VALUE, &drivers); + if (res) { - DWORD index = 0; - cbBufMax--; - success = TRUE; - while (cbBufMax > 0) - { - DWORD size_name; - size_name = cbBufMax; - if ((reg_ret = RegEnumValueW(hDrivers, index, lpszBuf, &size_name, NULL, NULL, NULL, NULL)) == ERROR_SUCCESS) - { - index++; - assert (size_name < cbBufMax && *(lpszBuf + size_name) == 0); - size_name++; - cbBufMax-= size_name; - lpszBuf+=size_name; - } - else - { - if (reg_ret != ERROR_NO_MORE_ITEMS) - { - success = FALSE; - push_error(ODBC_ERROR_GENERAL_ERR, odbc_error_general_err); - } - break; - } - } - *lpszBuf = 0; - if ((reg_ret = RegCloseKey (hDrivers)) != ERROR_SUCCESS) - TRACE ("Error %d closing ODBC Drivers key\n", reg_ret); - } - else - { - /* MSDN states that it returns failure with COMPONENT_NOT_FOUND in this case. - * Version 3.525.1117.0 (Windows 2000) does not; it actually returns success. - * I doubt if it will actually be an issue. - */ push_error(ODBC_ERROR_COMPONENT_NOT_FOUND, odbc_error_component_not_found); + return FALSE; } - return success; + + RegQueryInfoKeyW(drivers, 0, 0, 0, 0, 0, 0, 0, &valuelen, 0, 0, 0); + value = heap_alloc(++valuelen * sizeof(WCHAR)); + + size--; + + while (1) + { + len = valuelen; + res = RegEnumValueW(drivers, index++, value, &len, NULL, NULL, NULL, NULL); + if (res == ERROR_SUCCESS) + { + lstrcpynW(buf + written, value, size - written); + written += min(len + 1, size - written); + } + else if (res == ERROR_NO_MORE_ITEMS) + break; + else + { + push_error(ODBC_ERROR_GENERAL_ERR, odbc_error_general_err); + ret = FALSE; + break; + } + } + + buf[written++] = 0; + + heap_free(value); + RegCloseKey(drivers); + if (sizeout) + *sizeout = written; + return ret; }
-BOOL WINAPI SQLGetInstalledDrivers(LPSTR lpszBuf, WORD cbBufMax, - WORD *pcbBufOut) +BOOL WINAPI SQLGetInstalledDrivers(char *buf, WORD size, WORD *sizeout) { + WORD written; + WCHAR *wbuf; BOOL ret; - int size_wbuf = cbBufMax; - LPWSTR wbuf; - WORD size_used;
- TRACE("%p %d %p\n", lpszBuf, cbBufMax, pcbBufOut); + TRACE("%p %d %p\n", buf, size, sizeout);
- wbuf = HeapAlloc(GetProcessHeap(), 0, size_wbuf*sizeof(WCHAR)); - if (wbuf) + if (!buf || !size) { - ret = SQLGetInstalledDriversW(wbuf, size_wbuf, &size_used); - if (ret) - { - if (!(ret = SQLInstall_narrow(2, lpszBuf, wbuf, size_used, cbBufMax, pcbBufOut))) - { - push_error(ODBC_ERROR_GENERAL_ERR, odbc_error_general_err); - } - } - HeapFree(GetProcessHeap(), 0, wbuf); - /* ignore failure; we have achieved the aim */ + push_error(ODBC_ERROR_INVALID_BUFF_LEN, odbc_error_invalid_buff_len); + return FALSE; } - else + + wbuf = heap_alloc(size * sizeof(WCHAR)); + if (!wbuf) { push_error(ODBC_ERROR_OUT_OF_MEM, odbc_error_out_of_mem); - ret = FALSE; + return FALSE; } - return ret; + + ret = SQLGetInstalledDriversW(wbuf, size, &written); + if (!ret) + return FALSE; + + *sizeout = WideCharToMultiByte(CP_ACP, 0, wbuf, written, NULL, 0, NULL, NULL); + WideCharToMultiByte(CP_ACP, 0, wbuf, written, buf, size, NULL, NULL); + + heap_free(wbuf); + return TRUE; }
static HKEY get_privateprofile_sectionkey(LPCWSTR section, LPCWSTR filename)
Signed-off-by: Hans Leidekker hans@codeweavers.com
Zebediah Figura z.figura12@gmail.com writes:
- RegQueryInfoKeyW(drivers, 0, 0, 0, 0, 0, 0, 0, &valuelen, 0, 0, 0);
- value = heap_alloc(++valuelen * sizeof(WCHAR));
I'll put this is for now, but note that using RegQueryInfoKey() is almost always a bug. There's no guarantee that the maximum size won't change, so the right way is to grow the buffer as needed.
On 22/05/18 09:46, Alexandre Julliard wrote:
Zebediah Figura z.figura12@gmail.com writes:
- RegQueryInfoKeyW(drivers, 0, 0, 0, 0, 0, 0, 0, &valuelen, 0, 0, 0);
- value = heap_alloc(++valuelen * sizeof(WCHAR));
I'll put this is for now, but note that using RegQueryInfoKey() is almost always a bug. There's no guarantee that the maximum size won't change, so the right way is to grow the buffer as needed.
Thanks, I'll send a patch to fix it after today's commits.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/odbccp32/tests/misc.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+)
diff --git a/dlls/odbccp32/tests/misc.c b/dlls/odbccp32/tests/misc.c index 4a72ad0..36cd4f5 100644 --- a/dlls/odbccp32/tests/misc.c +++ b/dlls/odbccp32/tests/misc.c @@ -27,6 +27,15 @@ static const WCHAR abcd_key[] = {'S','o','f','t','w','a','r','e','\','O','D','B','C','\','a','b','c','d','.','I','N','I','\','w','i','n','e','o','d','b','c',0}; static const WCHAR abcdini_key[] = {'S','o','f','t','w','a','r','e','\','O','D','B','C','\','a','b','c','d','.','I','N','I',0 };
+static void check_error_(int line, DWORD expect) +{ + RETCODE ret; + DWORD err; + ret = SQLInstallerError(1, &err, NULL, 0, NULL); + ok_(__FILE__, line)(ret == SQL_SUCCESS_WITH_INFO, "got %d\n", ret); + ok_(__FILE__, line)(err == expect, "expected %u, got %u\n", expect, ret); +} +#define check_error(a) check_error_(__LINE__, a)
static void test_SQLConfigMode(void) { @@ -605,6 +614,63 @@ static void test_SQLInstallTranslatorEx(void)
}
+static void test_SQLGetInstalledDrivers(void) +{ + char buffer[1000], *p; + WORD written, len; + int found = 0; + BOOL ret; + + SQLInstallDriverEx("Wine test\0Driver=test.dll\0\0", NULL, buffer, + sizeof(buffer), &written, ODBC_INSTALL_COMPLETE, NULL); + + ret = SQLGetInstalledDrivers(NULL, sizeof(buffer), &written); + ok(!ret, "got %d\n", ret); + check_error(ODBC_ERROR_INVALID_BUFF_LEN); + + ret = SQLGetInstalledDrivers(buffer, 0, &written); + ok(!ret, "got %d\n", ret); + check_error(ODBC_ERROR_INVALID_BUFF_LEN); + + ret = SQLGetInstalledDrivers(buffer, 10, &written); + ok(ret, "got %d\n", ret); + ok(strlen(buffer) == 8, "got len %zu\n", strlen(buffer)); + ok(written == 10, "got written %d\n", written); + ok(!buffer[9], "buffer not doubly null-terminated\n"); + + ret = SQLGetInstalledDrivers(buffer, sizeof(buffer), &written); + ok(ret, "got %d\n", ret); + ok(!buffer[written-1] && !buffer[written-2], "buffer not doubly null-terminated\n"); + len = strlen(buffer); + + for (p = buffer; *p; p += strlen(p) + 1) + { + if (!strcmp(p, "Wine test")) + found = 1; + } + ok(found, "installed driver not found\n"); + + ret = SQLGetInstalledDrivers(buffer, len, &written); + ok(ret, "got %d\n", ret); + ok(strlen(buffer) == len-2, "expected len %d, got %zu\n", len-2, strlen(buffer)); + ok(written == len, "expected written %d, got %d\n", len, written); + ok(!buffer[len-1], "buffer not doubly null-terminated\n"); + + ret = SQLGetInstalledDrivers(buffer, len+1, &written); + ok(ret, "got %d\n", ret); + ok(strlen(buffer) == len-1, "expected len %d, got %zu\n", len-1, strlen(buffer)); + ok(written == len+1, "expected written %d, got %d\n", len+1, written); + ok(!buffer[len], "buffer not doubly null-terminated\n"); + + ret = SQLGetInstalledDrivers(buffer, len+2, &written); + ok(ret, "got %d\n", ret); + ok(strlen(buffer) == len, "expected len %d, got %zu\n", len, strlen(buffer)); + ok(written == len+2, "expected written %d, got %d\n", len+2, written); + ok(!buffer[len+1], "buffer not doubly null-terminated\n"); + + SQLRemoveDriver("Wine test", TRUE, NULL); +} + START_TEST(misc) { test_SQLConfigMode(); @@ -615,4 +681,5 @@ START_TEST(misc) test_SQLGetPrivateProfileStringW(); test_SQLInstallDriverEx(); test_SQLInstallTranslatorEx(); + test_SQLGetInstalledDrivers(); }
Signed-off-by: Hans Leidekker hans@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/msi/tests/Makefile.in | 2 +- dlls/msi/tests/action.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-)
diff --git a/dlls/msi/tests/Makefile.in b/dlls/msi/tests/Makefile.in index 2cfc59b..43a5657 100644 --- a/dlls/msi/tests/Makefile.in +++ b/dlls/msi/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = msi.dll -IMPORTS = cabinet msi shell32 ole32 oleaut32 user32 advapi32 version +IMPORTS = cabinet msi shell32 ole32 oleaut32 user32 advapi32 version odbccp32
custom_IMPORTS = uuid msi ole32 shell32 advapi32
diff --git a/dlls/msi/tests/action.c b/dlls/msi/tests/action.c index d2fad6c..e33decc 100644 --- a/dlls/msi/tests/action.c +++ b/dlls/msi/tests/action.c @@ -32,6 +32,7 @@ #include <wtypes.h> #include <shellapi.h> #include <winsvc.h> +#include <odbcinst.h>
#include "wine/test.h" #include "utils.h" @@ -825,18 +826,22 @@ static const char odbc_feature_comp_dat[] = "Feature_\tComponent_\n" "s38\ts72\n" "FeatureComponents\tFeature_\tComponent_\n" + "odbc\todbc64\n" "odbc\todbc\n";
static const char odbc_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n" "s72\tS38\ts72\ti2\tS255\tS72\n" "Component\tComponent\n" + "odbc64\t{B6F3E4AF-35D1-4B72-9044-989F03E20A43}\tMSITESTDIR\t256\tMsix64\tODBCdriver.dll\n" "odbc\t{B6F3E4AE-35D1-4B72-9044-989F03E20A43}\tMSITESTDIR\t0\t\tODBCdriver.dll\n";
static const char odbc_driver_dat[] = "Driver\tComponent_\tDescription\tFile_\tFile_Setup\n" "s72\ts72\ts255\ts72\tS72\n" "ODBCDriver\tDriver\n" + "64-bit driver\todbc64\tODBC test driver\tODBCdriver.dll\t\n" + "64-bit driver2\todbc64\tODBC test driver2\tODBCdriver2.dll\tODBCsetup.dll\n" "ODBC test driver\todbc\tODBC test driver\tODBCdriver.dll\t\n" "ODBC test driver2\todbc\tODBC test driver2\tODBCdriver2.dll\tODBCsetup.dll\n";
@@ -5347,6 +5352,9 @@ error:
static void test_install_remove_odbc(void) { + int gotdriver = 0, gotdriver2 = 0; + char buffer[1000], *p; + WORD len; UINT r;
if (is_process_limited()) @@ -5379,6 +5387,19 @@ static void test_install_remove_odbc(void) ok(pf_exists("msitest\ODBCtranslator2.dll"), "file not created\n"); ok(pf_exists("msitest\ODBCsetup.dll"), "file not created\n");
+ r = SQLGetInstalledDrivers(buffer, sizeof(buffer), &len); + ok(len < sizeof(buffer), "buffer too small\n"); + ok(r, "SQLGetInstalledDrivers failed\n"); + for (p = buffer; *p; p += strlen(p) + 1) + { + if (!strcmp(p, "ODBC test driver")) + gotdriver = 1; + if (!strcmp(p, "ODBC test driver2")) + gotdriver2 = 1; + } + ok(gotdriver, "driver not installed\n"); + ok(gotdriver2, "driver 2 not installed\n"); + r = MsiInstallProductA(msifile, "REMOVE=ALL"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
@@ -5389,6 +5410,20 @@ static void test_install_remove_odbc(void) ok(!delete_pf("msitest\ODBCsetup.dll", TRUE), "file not removed\n"); ok(!delete_pf("msitest", FALSE), "directory not removed\n");
+ gotdriver = gotdriver2 = 0; + r = SQLGetInstalledDrivers(buffer, sizeof(buffer), &len); + ok(len < sizeof(buffer), "buffer too small\n"); + ok(r, "SQLGetInstalledDrivers failed\n"); + for (p = buffer; *p; p += strlen(p) + 1) + { + if (!strcmp(p, "ODBC test driver")) + gotdriver = 1; + if (!strcmp(p, "ODBC test driver2")) + gotdriver2 = 1; + } + ok(!gotdriver, "driver not installed\n"); + ok(!gotdriver2, "driver 2 not installed\n"); + error: DeleteFileA("msitest\ODBCdriver.dll"); DeleteFileA("msitest\ODBCdriver2.dll");
Signed-off-by: Hans Leidekker hans@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/msi/tests/Makefile.in | 2 +- dlls/msi/tests/action.c | 14 +++++++++++++ dlls/msi/tests/custom.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++ dlls/msi/tests/custom.spec | 2 ++ 4 files changed, 66 insertions(+), 1 deletion(-)
diff --git a/dlls/msi/tests/Makefile.in b/dlls/msi/tests/Makefile.in index 43a5657..18a6457 100644 --- a/dlls/msi/tests/Makefile.in +++ b/dlls/msi/tests/Makefile.in @@ -1,7 +1,7 @@ TESTDLL = msi.dll IMPORTS = cabinet msi shell32 ole32 oleaut32 user32 advapi32 version odbccp32
-custom_IMPORTS = uuid msi ole32 shell32 advapi32 +custom_IMPORTS = uuid msi ole32 shell32 advapi32 odbccp32
SOURCES = \ action.c \ diff --git a/dlls/msi/tests/action.c b/dlls/msi/tests/action.c index e33decc..943c939 100644 --- a/dlls/msi/tests/action.c +++ b/dlls/msi/tests/action.c @@ -870,7 +870,11 @@ static const char odbc_install_exec_seq_dat[] = "InstallInitialize\t\t1500\n" "ProcessComponents\t\t1600\n" "InstallODBC\t\t3000\n" + "io_immediate\tNOT REMOVE\t3001\n" + "io_deferred\tNOT REMOVE\t3002\n" "RemoveODBC\t\t3100\n" + "ro_immediate\tREMOVE\t3101\n" + "ro_deferred\tREMOVE\t3102\n" "RemoveFiles\t\t3900\n" "InstallFiles\t\t4000\n" "RegisterProduct\t\t5000\n" @@ -878,6 +882,15 @@ static const char odbc_install_exec_seq_dat[] = "PublishProduct\t\t5200\n" "InstallFinalize\t\t6000\n";
+static const char odbc_custom_action_dat[] = + "Action\tType\tSource\tTarget\n" + "s72\ti2\tS64\tS0\n" + "CustomAction\tAction\n" + "io_immediate\t1\tcustom.dll\todbc_absent\n" + "io_deferred\t1025\tcustom.dll\todbc_present\n" + "ro_immediate\t1\tcustom.dll\todbc_present\n" + "ro_deferred\t1025\tcustom.dll\todbc_absent\n"; + static const char odbc_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n" "i2\ti4\tL64\tS255\tS32\tS72\n" @@ -1969,6 +1982,7 @@ static const msi_table odbc_tables[] = ADD_TABLE(odbc_translator), ADD_TABLE(odbc_datasource), ADD_TABLE(odbc_install_exec_seq), + ADD_TABLE(odbc_custom_action), ADD_TABLE(odbc_media), ADD_TABLE(property) }; diff --git a/dlls/msi/tests/custom.c b/dlls/msi/tests/custom.c index 8a76ef9..cd805a6 100644 --- a/dlls/msi/tests/custom.c +++ b/dlls/msi/tests/custom.c @@ -24,6 +24,7 @@ #include <windef.h> #include <winbase.h> #include <winsvc.h> +#include <odbcinst.h> #define COBJMACROS #include <shlobj.h> #include <msxml.h> @@ -1314,3 +1315,51 @@ todo_wine_if(!MsiGetMode(hinst, MSIRUNMODE_SCHEDULED)) { ok(hinst, !pf_exists("msitest\duplicate2.txt"), "file present\n"); return ERROR_SUCCESS; } + +UINT WINAPI odbc_present(MSIHANDLE hinst) +{ + int gotdriver = 0, gotdriver2 = 0; + char buffer[1000], *p; + WORD len; + BOOL r; + + r = SQLGetInstalledDrivers(buffer, sizeof(buffer), &len); + ok(hinst, len < sizeof(buffer), "buffer too small\n"); + ok(hinst, r, "SQLGetInstalledDrivers failed\n"); + for (p = buffer; *p; p += strlen(p) + 1) + { + if (!strcmp(p, "ODBC test driver")) + gotdriver = 1; + if (!strcmp(p, "ODBC test driver2")) + gotdriver2 = 1; + } +todo_wine_if(!MsiGetMode(hinst, MSIRUNMODE_SCHEDULED)) { + ok(hinst, gotdriver, "driver absent\n"); + ok(hinst, gotdriver2, "driver 2 absent\n"); +} + return ERROR_SUCCESS; +} + +UINT WINAPI odbc_absent(MSIHANDLE hinst) +{ + int gotdriver = 0, gotdriver2 = 0; + char buffer[1000], *p; + WORD len; + BOOL r; + + r = SQLGetInstalledDrivers(buffer, sizeof(buffer), &len); + ok(hinst, len < sizeof(buffer), "buffer too small\n"); + ok(hinst, r, "SQLGetInstalledDrivers failed\n"); + for (p = buffer; *p; p += strlen(p) + 1) + { + if (!strcmp(p, "ODBC test driver")) + gotdriver = 1; + if (!strcmp(p, "ODBC test driver2")) + gotdriver2 = 1; + } +todo_wine_if(!MsiGetMode(hinst, MSIRUNMODE_SCHEDULED)) { + ok(hinst, !gotdriver, "driver present\n"); + ok(hinst, !gotdriver2, "driver 2 present\n"); +} + return ERROR_SUCCESS; +} diff --git a/dlls/msi/tests/custom.spec b/dlls/msi/tests/custom.spec index 1b15ca9..52feffa 100644 --- a/dlls/msi/tests/custom.spec +++ b/dlls/msi/tests/custom.spec @@ -9,6 +9,8 @@ @ stdcall crs_absent(long) @ stdcall file_present(long) @ stdcall file_absent(long) +@ stdcall odbc_present(long) +@ stdcall odbc_absent(long) @ stdcall rd_present(long) @ stdcall rd_absent(long) @ stdcall sds_present(long)
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check? Full results can be found at https://testbot.winehq.org/JobDetails.pl?Key=38524
Your paranoid android.
=== w7pro64 (32 bit custom) === The previous 1 run(s) terminated abnormally
=== w7pro64 (64 bit custom) === The previous 1 run(s) terminated abnormally
=== wvistau64_zh_CN (32 bit action) === custom.c:1233: Test failed: service present msi:action contains a misplaced failure message for custom
=== w7u (32 bit action) === The previous 1 run(s) terminated abnormally
=== w7u (32 bit patch) === TestBot process got stuck or died unexpectedly The previous 1 run(s) terminated abnormally
=== wxppro (32 bit install) === msi:install contains a misplaced failure message for custom
=== wxppro (32 bit suminfo) === TestBot process got stuck or died unexpectedly The previous 1 run(s) terminated abnormally
=== w7u (32 bit msi) === The previous 2 run(s) terminated abnormally
Signed-off-by: Hans Leidekker hans@codeweavers.com
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check? Full results can be found at https://testbot.winehq.org/JobDetails.pl?Key=38520
Your paranoid android.
=== wxppro (32 bit install) === msi:install contains a misplaced failure message for custom
=== w7pro64 (32 bit custom) === The previous 1 run(s) terminated abnormally
=== w7pro64 (64 bit custom) === The previous 1 run(s) terminated abnormally