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@gmail.com> Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
6a3dbf1192
commit
942964fdfb
|
@ -778,10 +778,36 @@ MSIDBERROR WINAPI MsiViewGetErrorW( MSIHANDLE handle, LPWSTR buffer, LPDWORD buf
|
||||||
if (!buflen)
|
if (!buflen)
|
||||||
return MSIDBERROR_INVALIDARG;
|
return MSIDBERROR_INVALIDARG;
|
||||||
|
|
||||||
query = msihandle2msiinfo( handle, MSIHANDLETYPE_VIEW );
|
if (!(query = msihandle2msiinfo(handle, MSIHANDLETYPE_VIEW)))
|
||||||
if( !query )
|
{
|
||||||
|
WCHAR *remote_column = NULL;
|
||||||
|
MSIHANDLE remote;
|
||||||
|
|
||||||
|
if (!(remote = msi_get_remote(handle)))
|
||||||
return MSIDBERROR_INVALIDARG;
|
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;
|
if ((r = query->view->error)) column = query->view->error_column;
|
||||||
else column = szEmpty;
|
else column = szEmpty;
|
||||||
|
|
||||||
|
@ -803,10 +829,36 @@ MSIDBERROR WINAPI MsiViewGetErrorA( MSIHANDLE handle, LPSTR buffer, LPDWORD bufl
|
||||||
if (!buflen)
|
if (!buflen)
|
||||||
return MSIDBERROR_INVALIDARG;
|
return MSIDBERROR_INVALIDARG;
|
||||||
|
|
||||||
query = msihandle2msiinfo( handle, MSIHANDLETYPE_VIEW );
|
if (!(query = msihandle2msiinfo(handle, MSIHANDLETYPE_VIEW)))
|
||||||
if (!query)
|
{
|
||||||
|
WCHAR *remote_column = NULL;
|
||||||
|
MSIHANDLE remote;
|
||||||
|
|
||||||
|
if (!(remote = msi_get_remote(handle)))
|
||||||
return MSIDBERROR_INVALIDARG;
|
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;
|
if ((r = query->view->error)) column = query->view->error_column;
|
||||||
else column = szEmpty;
|
else column = szEmpty;
|
||||||
|
|
||||||
|
@ -1199,6 +1251,22 @@ UINT __cdecl s_remote_ViewGetColumnInfo(MSIHANDLE view, MSICOLINFO info, struct
|
||||||
return r;
|
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,
|
UINT __cdecl s_remote_ViewModify(MSIHANDLE view, MSIMODIFY mode,
|
||||||
struct wire_record *remote_rec, struct wire_record **remote_refreshed)
|
struct wire_record *remote_rec, struct wire_record **remote_refreshed)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1159,6 +1159,109 @@ static void test_invalid_functions(MSIHANDLE hinst)
|
||||||
MsiCloseHandle(db);
|
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
|
/* Main test. Anything that doesn't depend on a specific install configuration
|
||||||
* or have undesired side effects should go here. */
|
* or have undesired side effects should go here. */
|
||||||
UINT WINAPI main_test(MSIHANDLE hinst)
|
UINT WINAPI main_test(MSIHANDLE hinst)
|
||||||
|
@ -1186,6 +1289,7 @@ UINT WINAPI main_test(MSIHANDLE hinst)
|
||||||
test_format_record(hinst);
|
test_format_record(hinst);
|
||||||
test_costs(hinst);
|
test_costs(hinst);
|
||||||
test_invalid_functions(hinst);
|
test_invalid_functions(hinst);
|
||||||
|
test_view_get_error(hinst);
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -700,6 +700,19 @@ static const CHAR ca1_test_seq_dat[] = "Action\tCondition\tSequence\n"
|
||||||
"nested1\t\t1\n"
|
"nested1\t\t1\n"
|
||||||
"nested51\t\t2\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"
|
static const CHAR ca51_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
|
||||||
"s72\tS38\ts72\ti2\tS255\tS72\n"
|
"s72\tS38\ts72\ti2\tS255\tS72\n"
|
||||||
"Component\tComponent\n"
|
"Component\tComponent\n"
|
||||||
|
@ -1714,6 +1727,8 @@ static const msi_table ca1_tables[] =
|
||||||
ADD_TABLE(ca1_install_exec_seq),
|
ADD_TABLE(ca1_install_exec_seq),
|
||||||
ADD_TABLE(ca1_custom_action),
|
ADD_TABLE(ca1_custom_action),
|
||||||
ADD_TABLE(ca1_test_seq),
|
ADD_TABLE(ca1_test_seq),
|
||||||
|
ADD_TABLE(ca1_test2),
|
||||||
|
ADD_TABLE(ca1__validation),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const msi_table ca51_tables[] =
|
static const msi_table ca51_tables[] =
|
||||||
|
|
|
@ -32,6 +32,7 @@ typedef int INSTALLSTATE;
|
||||||
typedef int MSICOLINFO;
|
typedef int MSICOLINFO;
|
||||||
typedef int MSIMODIFY;
|
typedef int MSIMODIFY;
|
||||||
typedef int MSICOSTTREE;
|
typedef int MSICOSTTREE;
|
||||||
|
typedef int MSIDBERROR;
|
||||||
|
|
||||||
#define MSIFIELD_NULL 0
|
#define MSIFIELD_NULL 0
|
||||||
#define MSIFIELD_INT 1
|
#define MSIFIELD_INT 1
|
||||||
|
@ -68,6 +69,7 @@ interface IWineMsiRemote
|
||||||
UINT remote_ViewExecute( [in] MSIHANDLE view, [in, unique] struct wire_record *record );
|
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_ViewFetch( [in] MSIHANDLE view, [out] struct wire_record **record );
|
||||||
UINT remote_ViewGetColumnInfo( [in] MSIHANDLE view, [in] MSICOLINFO info, [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,
|
UINT remote_ViewModify( [in] MSIHANDLE view, [in] MSIMODIFY mode,
|
||||||
[in] struct wire_record *record, [out] struct wire_record **refreshed );
|
[in] struct wire_record *record, [out] struct wire_record **refreshed );
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue