diff --git a/dll/win32/msi/msipriv.h b/dll/win32/msi/msipriv.h index 5c74ef864f0..a0423a60061 100644 --- a/dll/win32/msi/msipriv.h +++ b/dll/win32/msi/msipriv.h @@ -39,6 +39,7 @@ #include "wine/debug.h" #include "msiserver.h" +#include "winemsi.h" static const BOOL is_64bit = sizeof(void *) > sizeof(int); BOOL is_wow64 DECLSPEC_HIDDEN; @@ -830,6 +831,7 @@ extern BOOL MSI_RecordsAreFieldsEqual(MSIRECORD *a, MSIRECORD *b, UINT field) DE extern UINT msi_record_set_string(MSIRECORD *, UINT, const WCHAR *, int) DECLSPEC_HIDDEN; extern const WCHAR *msi_record_get_string(const MSIRECORD *, UINT, int *) DECLSPEC_HIDDEN; extern void dump_record(MSIRECORD *) DECLSPEC_HIDDEN; +extern UINT unmarshal_record(const struct wire_record *in, MSIHANDLE *out) DECLSPEC_HIDDEN; /* stream internals */ extern void enum_stream_names( IStorage *stg ) DECLSPEC_HIDDEN; diff --git a/dll/win32/msi/package.c b/dll/win32/msi/package.c index 483f6c4d597..87bd9f99861 100644 --- a/dll/win32/msi/package.c +++ b/dll/win32/msi/package.c @@ -2060,39 +2060,27 @@ INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType, MsiRecordGetInteger(hRecord, 1) != 2) return -1; + record = msihandle2msiinfo(hRecord, MSIHANDLETYPE_RECORD); + if (!record) + return ERROR_INVALID_HANDLE; + package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE ); if( !package ) { MSIHANDLE remote; - HRESULT hr; if (!(remote = msi_get_remote(hInstall))) return ERROR_INVALID_HANDLE; - hr = remote_ProcessMessage(remote, eMessageType, hRecord); + ret = remote_ProcessMessage(remote, eMessageType, (struct wire_record *)&record->count); - if (FAILED(hr)) - { - if (HRESULT_FACILITY(hr) == FACILITY_WIN32) - return HRESULT_CODE(hr); - - return ERROR_FUNCTION_FAILED; - } - - return ERROR_SUCCESS; + msiobj_release(&record->hdr); + return ret; } - record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD ); - if( !record ) - goto out; - ret = MSI_ProcessMessage( package, eMessageType, record ); -out: msiobj_release( &package->hdr ); - if( record ) - msiobj_release( &record->hdr ); - return ret; } @@ -2488,10 +2476,19 @@ UINT __cdecl remote_SetProperty(MSIHANDLE hinst, LPCWSTR property, LPCWSTR value return MsiSetPropertyW(hinst, property, value); } -HRESULT __cdecl remote_ProcessMessage(MSIHANDLE hinst, INSTALLMESSAGE message, MSIHANDLE record) +int __cdecl remote_ProcessMessage(MSIHANDLE hinst, INSTALLMESSAGE message, struct wire_record *remote_rec) { - UINT r = MsiProcessMessage(hinst, message, record); - return HRESULT_FROM_WIN32(r); + MSIHANDLE rec; + int ret; + UINT r; + + if ((r = unmarshal_record(remote_rec, &rec))) + return r; + + ret = MsiProcessMessage(hinst, message, rec); + + MsiCloseHandle(rec); + return ret; } HRESULT __cdecl remote_DoAction(MSIHANDLE hinst, BSTR action) diff --git a/dll/win32/msi/record.c b/dll/win32/msi/record.c index 8254b17f096..7b53d86edfe 100644 --- a/dll/win32/msi/record.c +++ b/dll/win32/msi/record.c @@ -1054,3 +1054,46 @@ void dump_record(MSIRECORD *rec) } TRACE("]\n"); } + +UINT unmarshal_record(const struct wire_record *in, MSIHANDLE *out) +{ + MSIRECORD *rec; + unsigned int i; + UINT r; + + rec = MSI_CreateRecord(in->count); + if (!rec) return ERROR_OUTOFMEMORY; + + for (i = 0; i <= in->count; i++) + { + switch (in->fields[i].type) + { + case MSIFIELD_NULL: + break; + case MSIFIELD_INT: + r = MSI_RecordSetInteger(rec, i, in->fields[i].u.iVal); + break; + case MSIFIELD_WSTR: + r = MSI_RecordSetStringW(rec, i, in->fields[i].u.szwVal); + break; + case MSIFIELD_STREAM: + r = MSI_RecordSetIStream(rec, i, in->fields[i].u.stream); + break; + default: + ERR("invalid field type %d\n", in->fields[i].type); + break; + } + + if (r) + { + msiobj_release(&rec->hdr); + return r; + } + } + + *out = alloc_msihandle(&rec->hdr); + if (!*out) return ERROR_OUTOFMEMORY; + + msiobj_release(&rec->hdr); + return ERROR_SUCCESS; +} diff --git a/dll/win32/msi/winemsi.idl b/dll/win32/msi/winemsi.idl index 7ea2e3cd57f..d97db4c0571 100644 --- a/dll/win32/msi/winemsi.idl +++ b/dll/win32/msi/winemsi.idl @@ -28,9 +28,29 @@ typedef int MSICONDITION; typedef int MSIRUNMODE; typedef int INSTALLSTATE; +#define MSIFIELD_NULL 0 +#define MSIFIELD_INT 1 +#define MSIFIELD_WSTR 3 +#define MSIFIELD_STREAM 4 cpp_quote("#endif") cpp_quote("#include \"msiquery.h\"") +struct wire_field { + unsigned int type; + [switch_is(type)] union { + [case(MSIFIELD_NULL)] ; + [case(MSIFIELD_INT)] int iVal; + [case(MSIFIELD_WSTR), string] LPWSTR szwVal; + [case(MSIFIELD_STREAM)] IStream *stream; + } u; + int len; +}; + +struct wire_record { + unsigned int count; + [size_is(count+1)] struct wire_field fields[]; +}; + [ uuid(56D58B64-8780-4c22-A8BC-8B0B29E4A9F8) ] @@ -44,7 +64,7 @@ interface IWineMsiRemote HRESULT remote_GetActiveDatabase( [in] MSIHANDLE hinst, [out] MSIHANDLE *handle ); UINT remote_GetProperty( [in] MSIHANDLE hinst, [in, string] LPCWSTR property, [out, string] LPWSTR *value, [out] DWORD *size ); UINT remote_SetProperty( [in] MSIHANDLE hinst, [in, string, unique] LPCWSTR property, [in, string, unique] LPCWSTR value ); - HRESULT remote_ProcessMessage( [in] MSIHANDLE hinst, [in] INSTALLMESSAGE message, [in] MSIHANDLE record ); + int remote_ProcessMessage( [in] MSIHANDLE hinst, [in] INSTALLMESSAGE message, [in] struct wire_record *record ); HRESULT remote_DoAction( [in] MSIHANDLE hinst, [in] BSTR action ); HRESULT remote_Sequence( [in] MSIHANDLE hinst, [in] BSTR table, [in] int sequence ); HRESULT remote_GetTargetPath( [in] MSIHANDLE hinst, [in] BSTR folder, [out, size_is(*size)] BSTR value, [in, out] DWORD *size );