[PATCH 3/6] msi: Make MsiFormatRecord() RPC-compatible.

Zebediah Figura z.figura12 at gmail.com
Tue Apr 24 22:27:39 CDT 2018


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/msi/format.c       | 34 +++++++----------
 dlls/msi/package.c      | 25 ++++++++-----
 dlls/msi/tests/custom.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++
 dlls/msi/winemsi.idl    |  2 +-
 4 files changed, 129 insertions(+), 31 deletions(-)

diff --git a/dlls/msi/format.c b/dlls/msi/format.c
index f15c4ce..0533cc0 100644
--- a/dlls/msi/format.c
+++ b/dlls/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/dlls/msi/package.c b/dlls/msi/package.c
index 6a5d689..4a46df1 100644
--- a/dlls/msi/package.c
+++ b/dlls/msi/package.c
@@ -2555,20 +2555,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/dlls/msi/tests/custom.c b/dlls/msi/tests/custom.c
index 35b1543..76a70ad 100644
--- a/dlls/msi/tests/custom.c
+++ b/dlls/msi/tests/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;
 }
diff --git a/dlls/msi/winemsi.idl b/dlls/msi/winemsi.idl
index a8e9348..7d7054a 100644
--- a/dlls/msi/winemsi.idl
+++ b/dlls/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,
-- 
2.7.4




More information about the wine-devel mailing list