https://git.reactos.org/?p=reactos.git;a=commitdiff;h=cde5f24cd967db9688d11…
commit cde5f24cd967db9688d11a0f559da2c4e1a128dc
Author: winesync <ros-dev(a)reactos.org>
AuthorDate: Sat Mar 12 15:12:05 2022 +0100
Commit: Mark Jansen <mark.jansen(a)reactos.org>
CommitDate: Sun Mar 20 19:27:41 2022 +0100
[WINESYNC] msi: Make MsiFormatRecord() RPC-compatible.
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 ef7ed29348584fc0385d42b707fd6fcc03dfddc5 by Zebediah Figura
<z.figura12(a)gmail.com>
---
dll/win32/msi/format.c | 34 +++++------
dll/win32/msi/package.c | 25 ++++++---
dll/win32/msi/winemsi.idl | 2 +-
modules/rostests/winetests/msi/custom.c | 99 +++++++++++++++++++++++++++++++++
4 files changed, 129 insertions(+), 31 deletions(-)
diff --git a/dll/win32/msi/format.c b/dll/win32/msi/format.c
index f15c4ceb60c..0533cc004ce 100644
--- a/dll/win32/msi/format.c
+++ b/dll/win32/msi/format.c
@@ -907,43 +907,35 @@ UINT WINAPI MsiFormatRecordW( MSIHANDLE hInstall, MSIHANDLE
hRecord,
TRACE("%d %d %p %p\n", hInstall, hRecord, szResult, sz);
+ record = msihandle2msiinfo(hRecord, MSIHANDLETYPE_RECORD);
+ if (!record)
+ return ERROR_INVALID_HANDLE;
+
package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
if (!package)
{
- HRESULT hr;
+ LPWSTR value = NULL;
MSIHANDLE remote;
- BSTR value = NULL;
awstring wstr;
if ((remote = msi_get_remote(hInstall)))
{
- hr = remote_FormatRecord(remote, hRecord, &value);
- if (FAILED(hr))
- goto done;
+ r = remote_FormatRecord(remote, (struct wire_record *)&record->count,
&value);
+ if (r)
+ {
+ midl_user_free(value);
+ return r;
+ }
wstr.unicode = TRUE;
wstr.str.w = szResult;
- r = msi_strcpy_to_awstring( value, SysStringLen(value), &wstr, sz );
-
-done:
- SysFreeString( value );
-
- if (FAILED(hr))
- {
- if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
- return HRESULT_CODE(hr);
-
- return ERROR_FUNCTION_FAILED;
- }
+ r = msi_strcpy_to_awstring(value, -1, &wstr, sz);
+ midl_user_free(value);
return r;
}
}
- record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD );
-
- if (!record)
- return ERROR_INVALID_HANDLE;
if (!sz)
{
msiobj_release( &record->hdr );
diff --git a/dll/win32/msi/package.c b/dll/win32/msi/package.c
index ca671f690c4..03335fb9d66 100644
--- a/dll/win32/msi/package.c
+++ b/dll/win32/msi/package.c
@@ -2562,20 +2562,27 @@ UINT __cdecl remote_SetInstallLevel(MSIHANDLE hinst, int level)
return MsiSetInstallLevel(hinst, level);
}
-HRESULT __cdecl remote_FormatRecord(MSIHANDLE hinst, MSIHANDLE record,
- BSTR *value)
+UINT __cdecl remote_FormatRecord(MSIHANDLE hinst, struct wire_record *remote_rec, LPWSTR
*value)
{
+ WCHAR empty[1];
DWORD size = 0;
- UINT r = MsiFormatRecordW(hinst, record, NULL, &size);
- if (r == ERROR_SUCCESS)
+ MSIHANDLE rec;
+ UINT r;
+
+ if ((r = unmarshal_record(remote_rec, &rec)))
+ return r;
+
+ r = MsiFormatRecordW(hinst, rec, empty, &size);
+ if (r == ERROR_MORE_DATA)
{
- *value = SysAllocStringLen(NULL, size);
+ *value = midl_user_allocate(++size * sizeof(WCHAR));
if (!*value)
- return E_OUTOFMEMORY;
- size++;
- r = MsiFormatRecordW(hinst, record, *value, &size);
+ return ERROR_OUTOFMEMORY;
+ r = MsiFormatRecordW(hinst, rec, *value, &size);
}
- return HRESULT_FROM_WIN32(r);
+
+ MsiCloseHandle(rec);
+ return r;
}
HRESULT __cdecl remote_EvaluateCondition(MSIHANDLE hinst, BSTR condition)
diff --git a/dll/win32/msi/winemsi.idl b/dll/win32/msi/winemsi.idl
index a8e9348ecdf..7d7054a7076 100644
--- a/dll/win32/msi/winemsi.idl
+++ b/dll/win32/msi/winemsi.idl
@@ -87,7 +87,7 @@ interface IWineMsiRemote
UINT remote_SetComponentState( [in] MSIHANDLE hinst, [in, string] LPCWSTR component,
[in] INSTALLSTATE state );
LANGID remote_GetLanguage( [in] MSIHANDLE hinst );
UINT remote_SetInstallLevel( [in] MSIHANDLE hinst, [in] int level );
- HRESULT remote_FormatRecord( [in] MSIHANDLE hinst, [in] MSIHANDLE record, [out] BSTR
*value );
+ UINT remote_FormatRecord( [in] MSIHANDLE hinst, [in] struct wire_record *record,
[out, string] LPWSTR *value);
HRESULT remote_EvaluateCondition( [in] MSIHANDLE hinst, [in] BSTR condition );
HRESULT remote_GetFeatureCost( [in] MSIHANDLE hinst, [in] BSTR feature, [in] INT
cost_tree, [in] INSTALLSTATE state, [out] INT *cost );
HRESULT remote_EnumComponentCosts( [in] MSIHANDLE hinst, [in] BSTR component, [in]
DWORD index, [in] INSTALLSTATE state,
diff --git a/modules/rostests/winetests/msi/custom.c
b/modules/rostests/winetests/msi/custom.c
index 35b1543407e..76a70adac40 100644
--- a/modules/rostests/winetests/msi/custom.c
+++ b/modules/rostests/winetests/msi/custom.c
@@ -750,6 +750,104 @@ static void test_feature_states(MSIHANDLE hinst)
ok(hinst, action == INSTALLSTATE_LOCAL, "got action %d\n", action);
}
+static void test_format_record(MSIHANDLE hinst)
+{
+ static const WCHAR xyzW[] = {'f','o','o','
','1','2','3',0};
+ static const WCHAR xyW[] = {'f','o','o','
','1','2',0};
+ WCHAR bufferW[10];
+ char buffer[10];
+ MSIHANDLE rec;
+ DWORD sz;
+ UINT r;
+
+ r = MsiFormatRecordA(hinst, 0, NULL, NULL);
+ ok(hinst, r == ERROR_INVALID_HANDLE, "got %u\n", r);
+
+ rec = MsiCreateRecord(1);
+ MsiRecordSetStringA(rec, 0, "foo [1]");
+ MsiRecordSetInteger(rec, 1, 123);
+
+ r = MsiFormatRecordA(hinst, rec, NULL, NULL);
+ ok(hinst, !r, "got %u\n", r);
+
+ r = MsiFormatRecordA(hinst, rec, buffer, NULL);
+ ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r);
+
+ /* Returned size is in bytes, not chars, but only for custom actions. */
+
+ sz = 0;
+ r = MsiFormatRecordA(hinst, rec, NULL, &sz);
+ ok(hinst, !r, "got %u\n", r);
+ todo_wine_ok(hinst, sz == 14, "got size %u\n", sz);
+
+ sz = 0;
+ strcpy(buffer,"q");
+ r = MsiFormatRecordA(hinst, rec, buffer, &sz);
+ ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
+ ok(hinst, !strcmp(buffer, "q"), "got \"%s\"\n",
buffer);
+ todo_wine_ok(hinst, sz == 14, "got size %u\n", sz);
+
+ sz = 1;
+ strcpy(buffer,"x");
+ r = MsiFormatRecordA(hinst, rec, buffer, &sz);
+ ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
+ ok(hinst, !buffer[0], "got \"%s\"\n", buffer);
+ todo_wine_ok(hinst, sz == 14, "got size %u\n", sz);
+
+ sz = 7;
+ strcpy(buffer,"x");
+ r = MsiFormatRecordA(hinst, rec, buffer, &sz);
+ ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
+ ok(hinst, !strcmp(buffer, "foo 12"), "got \"%s\"\n",
buffer);
+ todo_wine_ok(hinst, sz == 14, "got size %u\n", sz);
+
+ sz = 8;
+ strcpy(buffer,"x");
+ r = MsiFormatRecordA(hinst, rec, buffer, &sz);
+ ok(hinst, !r, "got %u\n", r);
+ ok(hinst, !strcmp(buffer, "foo 123"), "got \"%s\"\n",
buffer);
+ ok(hinst, sz == 7, "got size %u\n", sz);
+
+ sz = 0;
+ bufferW[0] = 'q';
+ r = MsiFormatRecordW(hinst, rec, bufferW, &sz);
+ ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
+ ok(hinst, bufferW[0] == 'q', "got %s\n", dbgstr_w(bufferW));
+ ok(hinst, sz == 7, "got size %u\n", sz);
+
+ sz = 1;
+ bufferW[0] = 'q';
+ r = MsiFormatRecordW(hinst, rec, bufferW, &sz);
+ ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
+ ok(hinst, !bufferW[0], "got %s\n", dbgstr_w(bufferW));
+ ok(hinst, sz == 7, "got size %u\n", sz);
+
+ sz = 7;
+ bufferW[0] = 'q';
+ r = MsiFormatRecordW(hinst, rec, bufferW, &sz);
+ ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
+ ok(hinst, !lstrcmpW(bufferW, xyW), "got %s\n", dbgstr_w(bufferW));
+ ok(hinst, sz == 7, "got size %u\n", sz);
+
+ sz = 8;
+ bufferW[0] = 'q';
+ r = MsiFormatRecordW(hinst, rec, bufferW, &sz);
+ ok(hinst, !r, "got %u\n", r);
+ ok(hinst, !lstrcmpW(bufferW, xyzW), "got %s\n", dbgstr_w(bufferW));
+ ok(hinst, sz == 7, "got size %u\n", sz);
+
+ /* check that properties work */
+ MsiSetPropertyA(hinst, "fmtprop", "foobar");
+ MsiRecordSetStringA(rec, 0, "[fmtprop]");
+ sz = sizeof(buffer);
+ r = MsiFormatRecordA(hinst, rec, buffer, &sz);
+ ok(hinst, !r, "got %u\n", r);
+ ok(hinst, !strcmp(buffer, "foobar"), "got \"%s\"\n",
buffer);
+ ok(hinst, sz == 6, "got size %u\n", sz);
+
+ MsiCloseHandle(rec);
+}
+
/* 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)
@@ -779,6 +877,7 @@ UINT WINAPI main_test(MSIHANDLE hinst)
test_targetpath(hinst);
test_misc(hinst);
test_feature_states(hinst);
+ test_format_record(hinst);
return ERROR_SUCCESS;
}