Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/msi/install.c | 46 +++++------------------- dlls/msi/package.c | 17 +++++++-- dlls/msi/tests/custom.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++ dlls/msi/tests/install.c | 11 ++++++ dlls/msi/winemsi.idl | 2 +- 5 files changed, 125 insertions(+), 42 deletions(-)
diff --git a/dlls/msi/install.c b/dlls/msi/install.c index 2a5ff40..68d8eb5 100644 --- a/dlls/msi/install.c +++ b/dlls/msi/install.c @@ -27,7 +27,6 @@ #include "windef.h" #include "winbase.h" #include "winerror.h" -#include "wine/debug.h" #include "msi.h" #include "msidefs.h" #include "objbase.h" @@ -35,6 +34,8 @@
#include "msipriv.h" #include "winemsi.h" +#include "wine/heap.h" +#include "wine/debug.h" #include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi); @@ -200,50 +201,19 @@ static UINT MSI_GetTargetPath( MSIHANDLE hInstall, LPCWSTR szFolder, package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE ); if (!package) { - MSIHANDLE remote; - HRESULT hr; LPWSTR value = NULL; - BSTR folder; - DWORD len; + MSIHANDLE remote;
if (!(remote = msi_get_remote(hInstall))) return ERROR_INVALID_HANDLE;
- folder = SysAllocString( szFolder ); - if (!folder) - return ERROR_OUTOFMEMORY; + r = remote_GetTargetPath(remote, szFolder, &value); + if (r != ERROR_SUCCESS) + return r;
- len = 0; - hr = remote_GetTargetPath(remote, folder, NULL, &len); - if (FAILED(hr)) - goto done; - - len++; - value = msi_alloc(len * sizeof(WCHAR)); - if (!value) - { - r = ERROR_OUTOFMEMORY; - goto done; - } - - hr = remote_GetTargetPath(remote, folder, value, &len); - if (FAILED(hr)) - goto done; - - r = msi_strcpy_to_awstring( value, len, szPathBuf, pcchPathBuf ); - -done: - SysFreeString( folder ); - msi_free( 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, szPathBuf, pcchPathBuf);
+ midl_user_free(value); return r; }
diff --git a/dlls/msi/package.c b/dlls/msi/package.c index 161ba81..d1a6923 100644 --- a/dlls/msi/package.c +++ b/dlls/msi/package.c @@ -2474,10 +2474,21 @@ UINT __cdecl remote_Sequence(MSIHANDLE hinst, LPCWSTR table, int sequence) return MsiSequenceW(hinst, table, sequence); }
-HRESULT __cdecl remote_GetTargetPath(MSIHANDLE hinst, BSTR folder, BSTR value, DWORD *size) +UINT __cdecl remote_GetTargetPath(MSIHANDLE hinst, LPCWSTR folder, LPWSTR *value) { - UINT r = MsiGetTargetPathW(hinst, folder, value, size); - return HRESULT_FROM_WIN32(r); + WCHAR empty[1]; + DWORD size = 0; + UINT r; + + r = MsiGetTargetPathW(hinst, folder, empty, &size); + if (r == ERROR_MORE_DATA) + { + *value = midl_user_allocate(++size * sizeof(WCHAR)); + if (!*value) + return ERROR_OUTOFMEMORY; + r = MsiGetTargetPathW(hinst, folder, *value, &size); + } + return r; }
HRESULT __cdecl remote_SetTargetPath(MSIHANDLE hinst, BSTR folder, BSTR value) diff --git a/dlls/msi/tests/custom.c b/dlls/msi/tests/custom.c index bfd1e85..5062ecd 100644 --- a/dlls/msi/tests/custom.c +++ b/dlls/msi/tests/custom.c @@ -453,6 +453,96 @@ UINT WINAPI nested(MSIHANDLE hinst) return ERROR_SUCCESS; }
+static void test_targetpath(MSIHANDLE hinst) +{ + static const WCHAR targetdirW[] = {'T','A','R','G','E','T','D','I','R',0}; + static const WCHAR xyzW[] = {'C',':','\',0}; + static const WCHAR xyW[] = {'C',':',0}; + char buffer[20]; + WCHAR bufferW[20]; + DWORD sz; + UINT r; + + /* test invalid values */ + r = MsiGetTargetPathA(hinst, NULL, NULL, NULL); + ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r); + + r = MsiGetTargetPathA(hinst, "TARGETDIR", NULL, NULL ); + ok(hinst, !r, "got %u\n", r); + + r = MsiGetTargetPathA(hinst, "TARGETDIR", buffer, NULL ); + ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r); + + /* Returned size is in bytes, not chars, but only for custom actions. + * Seems to be a casualty of RPC... */ + + sz = 0; + r = MsiGetTargetPathA(hinst, "TARGETDIR", NULL, &sz); + ok(hinst, !r, "got %u\n", r); + todo_wine_ok(hinst, sz == 6, "got size %u\n", sz); + + sz = 0; + strcpy(buffer,"q"); + r = MsiGetTargetPathA(hinst, "TARGETDIR", 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 == 6, "got size %u\n", sz); + + sz = 1; + strcpy(buffer,"x"); + r = MsiGetTargetPathA(hinst, "TARGETDIR", 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 == 6, "got size %u\n", sz); + + sz = 3; + strcpy(buffer,"x"); + r = MsiGetTargetPathA(hinst, "TARGETDIR", buffer, &sz); + ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r); + ok(hinst, !strcmp(buffer, "C:"), "got "%s"\n", buffer); + todo_wine_ok(hinst, sz == 6, "got size %u\n", sz); + + sz = 4; + strcpy(buffer,"x"); + r = MsiGetTargetPathA(hinst, "TARGETDIR", buffer, &sz); + ok(hinst, !r, "got %u\n", r); + ok(hinst, !strcmp(buffer, "C:\"), "got "%s"\n", buffer); + ok(hinst, sz == 3, "got size %u\n", sz); + + sz = 0; + r = MsiGetTargetPathW(hinst, targetdirW, NULL, &sz); + ok(hinst, !r, "got %u\n", r); + ok(hinst, sz == 3, "got size %u\n", sz); + + sz = 0; + bufferW[0] = 'q'; + r = MsiGetTargetPathW(hinst, targetdirW, 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 == 3, "got size %u\n", sz); + + sz = 1; + bufferW[0] = 'q'; + r = MsiGetTargetPathW(hinst, targetdirW, 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 == 3, "got size %u\n", sz); + + sz = 3; + bufferW[0] = 'q'; + r = MsiGetTargetPathW(hinst, targetdirW, 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 == 3, "got size %u\n", sz); + + sz = 4; + bufferW[0] = 'q'; + r = MsiGetTargetPathW(hinst, targetdirW, bufferW, &sz); + ok(hinst, !r, "got %u\n", r); + ok(hinst, !lstrcmpW(bufferW, xyzW), "got %s\n", dbgstr_w(bufferW)); + ok(hinst, sz == 3, "got size %u\n", sz); +} + /* 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) @@ -479,6 +569,7 @@ UINT WINAPI main_test(MSIHANDLE hinst) test_props(hinst); test_db(hinst); test_doaction(hinst); + test_targetpath(hinst);
return ERROR_SUCCESS; } diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c index c5d9243..6a7383b 100644 --- a/dlls/msi/tests/install.c +++ b/dlls/msi/tests/install.c @@ -695,6 +695,9 @@ static const CHAR wrv_component_dat[] = "Component\tComponentId\tDirectory_\tAtt static const CHAR ca1_install_exec_seq_dat[] = "Action\tCondition\tSequence\n" "s72\tS255\tI2\n" "InstallExecuteSequence\tAction\n" + "CostInitialize\t\t100\n" + "FileCost\t\t200\n" + "CostFinalize\t\t300\n" "embednull\t\t600\n" "maintest\tMAIN_TEST\t700\n" "testretval\tTEST_RETVAL\t710\n"; @@ -1709,7 +1712,13 @@ static const msi_table sf_tables[] =
static const msi_table ca1_tables[] = { + ADD_TABLE(component), + ADD_TABLE(directory), + ADD_TABLE(feature), + ADD_TABLE(feature_comp), + ADD_TABLE(file), ADD_TABLE(property), + ADD_TABLE(directory), ADD_TABLE(ca1_install_exec_seq), ADD_TABLE(ca1_custom_action), ADD_TABLE(ca1_test_seq), @@ -4120,6 +4129,7 @@ static void test_customaction1(void) MSIHANDLE hdb, record; UINT r;
+ create_test_files(); create_database(msifile, ca1_tables, sizeof(ca1_tables) / sizeof(msi_table)); add_custom_dll();
@@ -4158,6 +4168,7 @@ static void test_customaction1(void) r = MsiInstallProductA(msifile, "TEST_RETVAL=1"); ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
+ delete_test_files(); DeleteFileA(msifile); DeleteFileA("unus"); DeleteFileA("duo"); diff --git a/dlls/msi/winemsi.idl b/dlls/msi/winemsi.idl index d103e9a..5e09c85 100644 --- a/dlls/msi/winemsi.idl +++ b/dlls/msi/winemsi.idl @@ -76,7 +76,7 @@ interface IWineMsiRemote int remote_ProcessMessage( [in] MSIHANDLE hinst, [in] INSTALLMESSAGE message, [in] struct wire_record *record ); UINT remote_DoAction( [in] MSIHANDLE hinst, [in, string] LPCWSTR action ); UINT remote_Sequence( [in] MSIHANDLE hinst, [in, string] LPCWSTR table, [in] int sequence ); - HRESULT remote_GetTargetPath( [in] MSIHANDLE hinst, [in] BSTR folder, [out, size_is(*size)] BSTR value, [in, out] DWORD *size ); + UINT remote_GetTargetPath( [in] MSIHANDLE hinst, [in, string] LPCWSTR folder, [out, string] LPWSTR *value ); HRESULT remote_SetTargetPath( [in] MSIHANDLE hinst, [in] BSTR folder, [in] BSTR value ); HRESULT remote_GetSourcePath( [in] MSIHANDLE hinst, [in] BSTR folder, [out, size_is(*size)] BSTR value, [in, out] DWORD *size ); HRESULT remote_GetMode( [in] MSIHANDLE hinst, [in] MSIRUNMODE mode, [out] BOOL *ret );