https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d672ffc384062f7f91404…
commit d672ffc384062f7f914048b832dd65a0ac07be77
Author: winesync <ros-dev(a)reactos.org>
AuthorDate: Sun Mar 13 01:21:43 2022 +0100
Commit: Mark Jansen <mark.jansen(a)reactos.org>
CommitDate: Sun Mar 20 19:28:18 2022 +0100
[WINESYNC] msi: Handle the remote case in MsiViewGetError().
Wine-Bug:
https://bugs.winehq.org/show_bug.cgi?id=46830
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard(a)winehq.org>
wine commit id 942964fdfbd0cb2af1ea6a1c681fc73d399bcce3 by Zebediah Figura
<z.figura12(a)gmail.com>
---
dll/win32/msi/msiquery.c | 80 ++++++++++++++++++++++--
dll/win32/msi/winemsi.idl | 2 +
modules/rostests/winetests/msi/custom.c | 104 +++++++++++++++++++++++++++++++
modules/rostests/winetests/msi/install.c | 15 +++++
4 files changed, 195 insertions(+), 6 deletions(-)
diff --git a/dll/win32/msi/msiquery.c b/dll/win32/msi/msiquery.c
index 524cb7898b4..f04e98257c4 100644
--- a/dll/win32/msi/msiquery.c
+++ b/dll/win32/msi/msiquery.c
@@ -778,9 +778,35 @@ MSIDBERROR WINAPI MsiViewGetErrorW( MSIHANDLE handle, LPWSTR buffer,
LPDWORD buf
if (!buflen)
return MSIDBERROR_INVALIDARG;
- query = msihandle2msiinfo( handle, MSIHANDLETYPE_VIEW );
- if( !query )
- return MSIDBERROR_INVALIDARG;
+ if (!(query = msihandle2msiinfo(handle, MSIHANDLETYPE_VIEW)))
+ {
+ WCHAR *remote_column = NULL;
+ MSIHANDLE remote;
+
+ if (!(remote = msi_get_remote(handle)))
+ return MSIDBERROR_INVALIDARG;
+
+ if (!*buflen)
+ return MSIDBERROR_FUNCTIONERROR;
+
+ __TRY
+ {
+ r = remote_ViewGetError(remote, &remote_column);
+ }
+ __EXCEPT(rpc_filter)
+ {
+ r = GetExceptionCode();
+ }
+ __ENDTRY;
+
+ if (msi_strncpyW(remote_column ? remote_column : szEmpty, -1, buffer, buflen) ==
ERROR_MORE_DATA)
+ r = MSIDBERROR_MOREDATA;
+
+ if (remote_column)
+ midl_user_free(remote_column);
+
+ return r;
+ }
if ((r = query->view->error)) column = query->view->error_column;
else column = szEmpty;
@@ -803,9 +829,35 @@ MSIDBERROR WINAPI MsiViewGetErrorA( MSIHANDLE handle, LPSTR buffer,
LPDWORD bufl
if (!buflen)
return MSIDBERROR_INVALIDARG;
- query = msihandle2msiinfo( handle, MSIHANDLETYPE_VIEW );
- if (!query)
- return MSIDBERROR_INVALIDARG;
+ if (!(query = msihandle2msiinfo(handle, MSIHANDLETYPE_VIEW)))
+ {
+ WCHAR *remote_column = NULL;
+ MSIHANDLE remote;
+
+ if (!(remote = msi_get_remote(handle)))
+ return MSIDBERROR_INVALIDARG;
+
+ if (!*buflen)
+ return MSIDBERROR_FUNCTIONERROR;
+
+ __TRY
+ {
+ r = remote_ViewGetError(remote, &remote_column);
+ }
+ __EXCEPT(rpc_filter)
+ {
+ r = GetExceptionCode();
+ }
+ __ENDTRY;
+
+ if (msi_strncpyWtoA(remote_column ? remote_column : szEmpty, -1, buffer, buflen,
FALSE) == ERROR_MORE_DATA)
+ r = MSIDBERROR_MOREDATA;
+
+ if (remote_column)
+ midl_user_free(remote_column);
+
+ return r;
+ }
if ((r = query->view->error)) column = query->view->error_column;
else column = szEmpty;
@@ -1199,6 +1251,22 @@ UINT __cdecl s_remote_ViewGetColumnInfo(MSIHANDLE view, MSICOLINFO
info, struct
return r;
}
+MSIDBERROR __cdecl s_remote_ViewGetError(MSIHANDLE view, LPWSTR *column)
+{
+ WCHAR empty[1];
+ DWORD size = 1;
+ UINT r;
+
+ r = MsiViewGetErrorW(view, empty, &size);
+ if (r == MSIDBERROR_MOREDATA)
+ {
+ if (!(*column = midl_user_allocate(++size * sizeof(WCHAR))))
+ return MSIDBERROR_FUNCTIONERROR;
+ r = MsiViewGetErrorW(view, *column, &size);
+ }
+ return r;
+}
+
UINT __cdecl s_remote_ViewModify(MSIHANDLE view, MSIMODIFY mode,
struct wire_record *remote_rec, struct wire_record **remote_refreshed)
{
diff --git a/dll/win32/msi/winemsi.idl b/dll/win32/msi/winemsi.idl
index 16586036949..7888b0ceb40 100644
--- a/dll/win32/msi/winemsi.idl
+++ b/dll/win32/msi/winemsi.idl
@@ -32,6 +32,7 @@ typedef int INSTALLSTATE;
typedef int MSICOLINFO;
typedef int MSIMODIFY;
typedef int MSICOSTTREE;
+typedef int MSIDBERROR;
#define MSIFIELD_NULL 0
#define MSIFIELD_INT 1
@@ -68,6 +69,7 @@ interface IWineMsiRemote
UINT remote_ViewExecute( [in] MSIHANDLE view, [in, unique] struct wire_record *record
);
UINT remote_ViewFetch( [in] MSIHANDLE view, [out] struct wire_record **record );
UINT remote_ViewGetColumnInfo( [in] MSIHANDLE view, [in] MSICOLINFO info, [out]
struct wire_record **record );
+ MSIDBERROR remote_ViewGetError( [in] MSIHANDLE view, [out, string] LPWSTR *column );
UINT remote_ViewModify( [in] MSIHANDLE view, [in] MSIMODIFY mode,
[in] struct wire_record *record, [out] struct wire_record **refreshed );
diff --git a/modules/rostests/winetests/msi/custom.c
b/modules/rostests/winetests/msi/custom.c
index 43b8369b17f..3a189efff68 100644
--- a/modules/rostests/winetests/msi/custom.c
+++ b/modules/rostests/winetests/msi/custom.c
@@ -1159,6 +1159,109 @@ static void test_invalid_functions(MSIHANDLE hinst)
MsiCloseHandle(db);
}
+static void test_view_get_error(MSIHANDLE hinst)
+{
+ MSIHANDLE db, view, rec;
+ char buffer[5];
+ MSIDBERROR err;
+ DWORD sz;
+ UINT r;
+
+ db = MsiGetActiveDatabase(hinst);
+ ok(hinst, db, "MsiGetActiveDatabase failed\n");
+
+ r = MsiDatabaseOpenViewA(db, "SELECT * FROM `test2`", &view);
+ ok(hinst, !r, "got %u\n", r);
+
+ r = MsiViewExecute(view, 0);
+ ok(hinst, !r, "got %u\n", r);
+
+ sz = 0;
+ err = MsiViewGetErrorA(0, NULL, &sz);
+ todo_wine ok(hinst, err == MSIDBERROR_FUNCTIONERROR, "got %d\n", err);
+ ok(hinst, sz == 0, "got size %u\n", sz);
+
+ err = MsiViewGetErrorA(view, NULL, NULL);
+ ok(hinst, err == MSIDBERROR_INVALIDARG, "got %d\n", err);
+
+ sz = 0;
+ err = MsiViewGetErrorA(view, NULL, &sz);
+ ok(hinst, err == MSIDBERROR_FUNCTIONERROR, "got %d\n", err);
+ ok(hinst, sz == 0, "got size %u\n", sz);
+
+ sz = 0;
+ strcpy(buffer, "x");
+ err = MsiViewGetErrorA(view, buffer, &sz);
+ ok(hinst, err == MSIDBERROR_FUNCTIONERROR, "got %d\n", err);
+ ok(hinst, !strcmp(buffer, "x"), "got \"%s\"\n",
buffer);
+ ok(hinst, sz == 0, "got size %u\n", sz);
+
+ sz = 1;
+ strcpy(buffer, "x");
+ err = MsiViewGetErrorA(view, buffer, &sz);
+ ok(hinst, err == MSIDBERROR_NOERROR, "got %d\n", err);
+ ok(hinst, !buffer[0], "got \"%s\"\n", buffer);
+ ok(hinst, sz == 0, "got size %u\n", sz);
+
+ rec = MsiCreateRecord(2);
+ MsiRecordSetInteger(rec, 1, 1);
+ MsiRecordSetInteger(rec, 2, 2);
+ r = MsiViewModify(view, MSIMODIFY_VALIDATE_NEW, rec);
+ ok(hinst, r == ERROR_INVALID_DATA, "got %u\n", r);
+
+ sz = 2;
+ strcpy(buffer, "x");
+ err = MsiViewGetErrorA(view, buffer, &sz);
+ ok(hinst, err == MSIDBERROR_DUPLICATEKEY, "got %d\n", err);
+ ok(hinst, !strcmp(buffer, "A"), "got \"%s\"\n",
buffer);
+ ok(hinst, sz == 1, "got size %u\n", sz);
+
+ sz = 2;
+ strcpy(buffer, "x");
+ err = MsiViewGetErrorA(view, buffer, &sz);
+ todo_wine ok(hinst, err == MSIDBERROR_NOERROR, "got %d\n", err);
+ todo_wine ok(hinst, !buffer[0], "got \"%s\"\n", buffer);
+ todo_wine ok(hinst, sz == 0, "got size %u\n", sz);
+
+ r = MsiViewModify(view, MSIMODIFY_VALIDATE_NEW, rec);
+ ok(hinst, r == ERROR_INVALID_DATA, "got %u\n", r);
+
+ sz = 1;
+ strcpy(buffer, "x");
+ err = MsiViewGetErrorA(view, buffer, &sz);
+ ok(hinst, err == MSIDBERROR_MOREDATA, "got %d\n", err);
+ ok(hinst, !buffer[0], "got \"%s\"\n", buffer);
+ ok(hinst, sz == 1, "got size %u\n", sz);
+
+ sz = 1;
+ strcpy(buffer, "x");
+ err = MsiViewGetErrorA(view, buffer, &sz);
+ todo_wine ok(hinst, err == MSIDBERROR_NOERROR, "got %d\n", err);
+ ok(hinst, !buffer[0], "got \"%s\"\n", buffer);
+ todo_wine ok(hinst, sz == 0, "got size %u\n", sz);
+
+ r = MsiViewModify(view, MSIMODIFY_VALIDATE_NEW, rec);
+ ok(hinst, r == ERROR_INVALID_DATA, "got %u\n", r);
+
+ sz = 0;
+ strcpy(buffer, "x");
+ err = MsiViewGetErrorA(view, buffer, &sz);
+ ok(hinst, err == MSIDBERROR_FUNCTIONERROR, "got %d\n", err);
+ ok(hinst, !strcmp(buffer, "x"), "got \"%s\"\n",
buffer);
+ ok(hinst, sz == 0, "got size %u\n", sz);
+
+ sz = 0;
+ strcpy(buffer, "x");
+ err = MsiViewGetErrorA(view, buffer, &sz);
+ ok(hinst, err == MSIDBERROR_FUNCTIONERROR, "got %d\n", err);
+ ok(hinst, !strcmp(buffer, "x"), "got \"%s\"\n",
buffer);
+ ok(hinst, sz == 0, "got size %u\n", sz);
+
+ MsiCloseHandle(rec);
+ MsiCloseHandle(view);
+ MsiCloseHandle(db);
+}
+
/* Main test. Anything that doesn't depend on a specific install configuration
* or have undesired side effects should go here. */
UINT WINAPI main_test(MSIHANDLE hinst)
@@ -1186,6 +1289,7 @@ UINT WINAPI main_test(MSIHANDLE hinst)
test_format_record(hinst);
test_costs(hinst);
test_invalid_functions(hinst);
+ test_view_get_error(hinst);
return ERROR_SUCCESS;
}
diff --git a/modules/rostests/winetests/msi/install.c
b/modules/rostests/winetests/msi/install.c
index 27dc83f87e2..e348f327011 100644
--- a/modules/rostests/winetests/msi/install.c
+++ b/modules/rostests/winetests/msi/install.c
@@ -700,6 +700,19 @@ static const CHAR ca1_test_seq_dat[] =
"Action\tCondition\tSequence\n"
"nested1\t\t1\n"
"nested51\t\t2\n";
+static const CHAR ca1_test2_dat[] =
+ "A\tB\n"
+ "i2\ti2\n"
+ "test2\tA\n"
+ "1\t2\n";
+
+static const CHAR ca1__validation_dat[] =
+
"Table\tColumn\tNullable\tMinValue\tMaxValue\tKeyTable\tKeyColumn\tCategory\tSet\tDescription\n"
+ "s32\ts32\ts4\tI4\tI4\tS255\tI2\tS32\tS255\tS255\n"
+ "_Validation\tTable\tColumn\n"
+ "test2\tA\tN\t\t\t\t\t\t\t\n"
+ "test2\tB\tN\t\t\t\t\t\t\t\n";
+
static const CHAR ca51_component_dat[] =
"Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
"s72\tS38\ts72\ti2\tS255\tS72\n"
"Component\tComponent\n"
@@ -1714,6 +1727,8 @@ static const msi_table ca1_tables[] =
ADD_TABLE(ca1_install_exec_seq),
ADD_TABLE(ca1_custom_action),
ADD_TABLE(ca1_test_seq),
+ ADD_TABLE(ca1_test2),
+ ADD_TABLE(ca1__validation),
};
static const msi_table ca51_tables[] =