Signed-off-by: Zebediah Figura z.figura12@gmail.com --- v2: fix embedded nulls
dlls/msi/custom.c | 11 ++++++++ dlls/msi/package.c | 73 ++++++++++++++++++++++++---------------------------- dlls/msi/winemsi.idl | 2 +- 3 files changed, 46 insertions(+), 40 deletions(-)
diff --git a/dlls/msi/custom.c b/dlls/msi/custom.c index e2ed5a4..83b1687 100644 --- a/dlls/msi/custom.c +++ b/dlls/msi/custom.c @@ -34,6 +34,7 @@
#include "msipriv.h" #include "winemsi.h" +#include "wine/heap.h" #include "wine/debug.h" #include "wine/unicode.h" #include "wine/exception.h" @@ -64,6 +65,16 @@ static CRITICAL_SECTION msi_custom_action_cs = { &msi_custom_action_cs_debug, -1
static struct list msi_pending_custom_actions = LIST_INIT( msi_pending_custom_actions );
+void __RPC_FAR * __RPC_USER MIDL_user_allocate(SIZE_T len) +{ + return heap_alloc(len); +} + +void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr) +{ + heap_free(ptr); +} + UINT msi_schedule_action( MSIPACKAGE *package, UINT script, const WCHAR *action ) { UINT count; diff --git a/dlls/msi/package.c b/dlls/msi/package.c index 4e1ac2f..4986ec1 100644 --- a/dlls/msi/package.c +++ b/dlls/msi/package.c @@ -29,7 +29,6 @@ #include "winnls.h" #include "shlwapi.h" #include "wingdi.h" -#include "wine/debug.h" #include "msi.h" #include "msiquery.h" #include "objidl.h" @@ -39,11 +38,14 @@ #include "winver.h" #include "urlmon.h" #include "shlobj.h" -#include "wine/unicode.h" #include "objbase.h" #include "msidefs.h" #include "sddl.h"
+#include "wine/heap.h" +#include "wine/debug.h" +#include "wine/unicode.h" + #include "msipriv.h" #include "winemsi.h" #include "resource.h" @@ -2396,52 +2398,34 @@ static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name, package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE ); if (!package) { - HRESULT hr; - LPWSTR value = NULL; + LPWSTR value = NULL, buffer; MSIHANDLE remote; - BSTR bname;
if (!(remote = msi_get_remote(handle))) return ERROR_INVALID_HANDLE;
- bname = SysAllocString( name ); - if (!bname) - return ERROR_OUTOFMEMORY; + r = remote_GetProperty(remote, name, &value, &len); + if (r != ERROR_SUCCESS) + return r;
- hr = remote_GetProperty(remote, bname, NULL, &len); - if (FAILED(hr)) - goto done; - - len++; - value = msi_alloc(len * sizeof(WCHAR)); - if (!value) + /* String might contain embedded nulls. + * Native returns the correct size but truncates the string. */ + buffer = heap_alloc_zero((len + 1) * sizeof(WCHAR)); + if (!buffer) { - r = ERROR_OUTOFMEMORY; - goto done; + midl_user_free(value); + return ERROR_OUTOFMEMORY; } + strcpyW(buffer, value);
- hr = remote_GetProperty(remote, bname, value, &len); - if (FAILED(hr)) - goto done; - - r = msi_strcpy_to_awstring( value, len, szValueBuf, pchValueBuf ); + r = msi_strcpy_to_awstring(buffer, len, szValueBuf, pchValueBuf);
/* Bug required by Adobe installers */ - if (!szValueBuf->unicode && !szValueBuf->str.a) + if (pchValueBuf && !szValueBuf->unicode && !szValueBuf->str.a) *pchValueBuf *= sizeof(WCHAR);
-done: - SysFreeString(bname); - msi_free(value); - - if (FAILED(hr)) - { - if (HRESULT_FACILITY(hr) == FACILITY_WIN32) - return HRESULT_CODE(hr); - - return ERROR_FUNCTION_FAILED; - } - + heap_free(buffer); + midl_user_free(value); return r; }
@@ -2498,11 +2482,22 @@ HRESULT __cdecl remote_GetActiveDatabase(MSIHANDLE hinst, MSIHANDLE *handle) return S_OK; }
-HRESULT __cdecl remote_GetProperty(MSIHANDLE hinst, BSTR property, BSTR value, DWORD *size) +UINT __cdecl remote_GetProperty(MSIHANDLE hinst, LPCWSTR property, LPWSTR *value, DWORD *size) { - UINT r = MsiGetPropertyW(hinst, property, value, size); - if (r != ERROR_SUCCESS) return HRESULT_FROM_WIN32(r); - return S_OK; + WCHAR empty[1]; + UINT r; + + *size = 0; + r = MsiGetPropertyW(hinst, property, empty, size); + if (r == ERROR_MORE_DATA) + { + ++*size; + *value = midl_user_allocate(*size * sizeof(WCHAR)); + if (!*value) + return ERROR_OUTOFMEMORY; + r = MsiGetPropertyW(hinst, property, *value, size); + } + return r; }
HRESULT __cdecl remote_SetProperty(MSIHANDLE hinst, BSTR property, BSTR value) diff --git a/dlls/msi/winemsi.idl b/dlls/msi/winemsi.idl index 706eb99..d9695e6 100644 --- a/dlls/msi/winemsi.idl +++ b/dlls/msi/winemsi.idl @@ -40,7 +40,7 @@ interface IWineMsiRemote HRESULT remote_DatabaseOpenView( [in] MSIHANDLE db, [in] LPCWSTR query, [out] MSIHANDLE *view );
HRESULT remote_GetActiveDatabase( [in] MSIHANDLE hinst, [out] MSIHANDLE *handle ); - HRESULT remote_GetProperty( [in] MSIHANDLE hinst, [in] BSTR property, [out, size_is(*size)] BSTR value, [in, out] DWORD *size ); + UINT remote_GetProperty( [in] MSIHANDLE hinst, [in, string] LPCWSTR property, [out, string] LPWSTR *value, [out] DWORD *size ); HRESULT remote_SetProperty( [in] MSIHANDLE hinst, [in] BSTR property, [in] BSTR value ); HRESULT remote_ProcessMessage( [in] MSIHANDLE hinst, [in] INSTALLMESSAGE message, [in] MSIHANDLE record ); HRESULT remote_DoAction( [in] MSIHANDLE hinst, [in] BSTR action );
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/msi/package.c | 31 +++---------------------------- dlls/msi/winemsi.idl | 2 +- 2 files changed, 4 insertions(+), 29 deletions(-)
diff --git a/dlls/msi/package.c b/dlls/msi/package.c index 4986ec1..b154423 100644 --- a/dlls/msi/package.c +++ b/dlls/msi/package.c @@ -2203,35 +2203,11 @@ UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue if( !package ) { MSIHANDLE remote; - HRESULT hr; - BSTR name = NULL, value = NULL;
if (!(remote = msi_get_remote(hInstall))) return ERROR_INVALID_HANDLE;
- name = SysAllocString( szName ); - value = SysAllocString( szValue ); - if ((!name && szName) || (!value && szValue)) - { - SysFreeString( name ); - SysFreeString( value ); - return ERROR_OUTOFMEMORY; - } - - hr = remote_SetProperty(remote, name, value); - - SysFreeString( name ); - SysFreeString( value ); - - if (FAILED(hr)) - { - if (HRESULT_FACILITY(hr) == FACILITY_WIN32) - return HRESULT_CODE(hr); - - return ERROR_FUNCTION_FAILED; - } - - return ERROR_SUCCESS; + return remote_SetProperty(remote, szName, szValue); }
ret = msi_set_property( package->db, szName, szValue, -1 ); @@ -2500,10 +2476,9 @@ UINT __cdecl remote_GetProperty(MSIHANDLE hinst, LPCWSTR property, LPWSTR *value return r; }
-HRESULT __cdecl remote_SetProperty(MSIHANDLE hinst, BSTR property, BSTR value) +UINT __cdecl remote_SetProperty(MSIHANDLE hinst, LPCWSTR property, LPCWSTR value) { - UINT r = MsiSetPropertyW(hinst, property, value); - return HRESULT_FROM_WIN32(r); + return MsiSetPropertyW(hinst, property, value); }
HRESULT __cdecl remote_ProcessMessage(MSIHANDLE hinst, INSTALLMESSAGE message, MSIHANDLE record) diff --git a/dlls/msi/winemsi.idl b/dlls/msi/winemsi.idl index d9695e6..61f7a74 100644 --- a/dlls/msi/winemsi.idl +++ b/dlls/msi/winemsi.idl @@ -41,7 +41,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 ); - HRESULT remote_SetProperty( [in] MSIHANDLE hinst, [in] BSTR property, [in] BSTR value ); + 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 ); HRESULT remote_DoAction( [in] MSIHANDLE hinst, [in] BSTR action ); HRESULT remote_Sequence( [in] MSIHANDLE hinst, [in] BSTR table, [in] int sequence );
Signed-off-by: Hans Leidekker hans@codeweavers.com
Remove many redundant tests, and print relevant values on failure.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/msi/tests/package.c | 220 +++++++++++++++-------------------------------- 1 file changed, 68 insertions(+), 152 deletions(-)
diff --git a/dlls/msi/tests/package.c b/dlls/msi/tests/package.c index 2022953..6414891 100644 --- a/dlls/msi/tests/package.c +++ b/dlls/msi/tests/package.c @@ -2138,16 +2138,14 @@ static void test_condition(void) DeleteFileA(msifile); }
-static BOOL check_prop_empty( MSIHANDLE hpkg, const char * prop) +static void check_prop(MSIHANDLE hpkg, const char *prop, const char *expect) { - UINT r; - DWORD sz; - char buffer[2]; - - sz = sizeof buffer; - strcpy(buffer,"x"); - r = MsiGetPropertyA( hpkg, prop, buffer, &sz ); - return r == ERROR_SUCCESS && buffer[0] == 0 && sz == 0; + char buffer[20] = "x"; + DWORD sz = sizeof(buffer); + UINT r = MsiGetPropertyA(hpkg, prop, buffer, &sz); + ok(!r, "'%s': got %u\n", prop, r); + ok(sz == lstrlenA(buffer), "'%s': expected %u, got %u\n", prop, lstrlenA(buffer), sz); + ok(!strcmp(buffer, expect), "expected '%s', got '%s'\n", expect, buffer); }
static void test_props(void) @@ -2173,150 +2171,120 @@ static void test_props(void)
/* test invalid values */ r = MsiGetPropertyA( 0, NULL, NULL, NULL ); - ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n"); + ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
r = MsiGetPropertyA( hpkg, NULL, NULL, NULL ); - ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n"); + ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
r = MsiGetPropertyA( hpkg, "boo", NULL, NULL ); - ok( r == ERROR_SUCCESS, "wrong return val\n"); + ok(!r, "got %u\n", r);
r = MsiGetPropertyA( hpkg, "boo", buffer, NULL ); - ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n"); + ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
/* test retrieving an empty/nonexistent property */ sz = sizeof buffer; r = MsiGetPropertyA( hpkg, "boo", NULL, &sz ); - ok( r == ERROR_SUCCESS, "wrong return val\n"); - ok( sz == 0, "wrong size returned\n"); + ok(!r, "got %u\n", r); + ok(sz == 0, "got size %d\n", sz);
- check_prop_empty( hpkg, "boo"); sz = 0; strcpy(buffer,"x"); r = MsiGetPropertyA( hpkg, "boo", buffer, &sz ); - ok( r == ERROR_MORE_DATA, "wrong return val\n"); - ok( !strcmp(buffer,"x"), "buffer was changed\n"); - ok( sz == 0, "wrong size returned\n"); + ok(r == ERROR_MORE_DATA, "got %u\n", r); + ok(!strcmp(buffer,"x"), "got "%s"\n", buffer); + ok(sz == 0, "got size %u\n", sz);
sz = 1; strcpy(buffer,"x"); r = MsiGetPropertyA( hpkg, "boo", buffer, &sz ); - ok( r == ERROR_SUCCESS, "wrong return val\n"); - ok( buffer[0] == 0, "buffer was not changed\n"); - ok( sz == 0, "wrong size returned\n"); + ok(!r, "got %u\n", r); + ok(!buffer[0], "got "%s"\n", buffer); + ok(sz == 0, "got size %u\n", sz);
/* set the property to something */ r = MsiSetPropertyA( 0, NULL, NULL ); - ok( r == ERROR_INVALID_HANDLE, "wrong return val\n"); + ok(r == ERROR_INVALID_HANDLE, "got %u\n", r);
r = MsiSetPropertyA( hpkg, NULL, NULL ); - ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n"); + ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
r = MsiSetPropertyA( hpkg, "", NULL ); - ok( r == ERROR_SUCCESS, "wrong return val\n"); + ok(!r, "got %u\n", r);
- /* try set and get some illegal property identifiers */ r = MsiSetPropertyA( hpkg, "", "asdf" ); - ok( r == ERROR_FUNCTION_FAILED, "wrong return val\n"); + ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r);
r = MsiSetPropertyA( hpkg, "=", "asdf" ); - ok( r == ERROR_SUCCESS, "wrong return val\n"); + ok(!r, "got %u\n", r); + check_prop(hpkg, "=", "asdf");
r = MsiSetPropertyA( hpkg, " ", "asdf" ); - ok( r == ERROR_SUCCESS, "wrong return val\n"); + ok(!r, "got %u\n", r); + check_prop(hpkg, " ", "asdf");
r = MsiSetPropertyA( hpkg, "'", "asdf" ); - ok( r == ERROR_SUCCESS, "wrong return val\n"); - - sz = sizeof buffer; - buffer[0]=0; - r = MsiGetPropertyA( hpkg, "'", buffer, &sz ); - ok( r == ERROR_SUCCESS, "wrong return val\n"); - ok( !strcmp(buffer,"asdf"), "buffer was not changed\n"); + ok(!r, "got %u\n", r); + check_prop(hpkg, "'", "asdf");
/* set empty values */ r = MsiSetPropertyA( hpkg, "boo", NULL ); - ok( r == ERROR_SUCCESS, "wrong return val\n"); - ok( check_prop_empty( hpkg, "boo"), "prop wasn't empty\n"); + ok(!r, "got %u\n", r); + check_prop(hpkg, "boo", "");
r = MsiSetPropertyA( hpkg, "boo", "" ); - ok( r == ERROR_SUCCESS, "wrong return val\n"); - ok( check_prop_empty( hpkg, "boo"), "prop wasn't empty\n"); + ok(!r, "got %u\n", r); + check_prop(hpkg, "boo", "");
/* set a non-empty value */ r = MsiSetPropertyA( hpkg, "boo", "xyz" ); - ok( r == ERROR_SUCCESS, "wrong return val\n"); + ok(!r, "got %u\n", r); + check_prop(hpkg, "boo", "xyz"); + + r = MsiGetPropertyA(hpkg, "boo", NULL, NULL); + ok(!r, "got %u\n", r); + + r = MsiGetPropertyA(hpkg, "boo", buffer, NULL); + ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r); + + sz = 0; + r = MsiGetPropertyA(hpkg, "boo", NULL, &sz); + ok(!r, "got %u\n", r); + ok(sz == 3, "got size %u\n", sz); + + sz = 0; + strcpy(buffer, "q"); + r = MsiGetPropertyA(hpkg, "boo", buffer, &sz); + ok(r == ERROR_MORE_DATA, "got %u\n", r); + ok(!strcmp(buffer, "q"), "got "%s"", buffer); + ok(sz == 3, "got size %u\n", sz);
sz = 1; strcpy(buffer,"x"); r = MsiGetPropertyA( hpkg, "boo", buffer, &sz ); - ok( r == ERROR_MORE_DATA, "wrong return val\n"); - ok( buffer[0] == 0, "buffer was not changed\n"); - ok( sz == 3, "wrong size returned\n"); - - sz = 4; - strcpy(buffer,"x"); - r = MsiGetPropertyA( hpkg, "boo", buffer, &sz ); - ok( r == ERROR_SUCCESS, "wrong return val\n"); - ok( !strcmp(buffer,"xyz"), "buffer was not changed\n"); - ok( sz == 3, "wrong size returned\n"); + ok(r == ERROR_MORE_DATA, "got %u\n", r); + ok(!buffer[0], "got "%s"\n", buffer); + ok(sz == 3, "got size %u\n", sz);
sz = 3; strcpy(buffer,"x"); r = MsiGetPropertyA( hpkg, "boo", buffer, &sz ); - ok( r == ERROR_MORE_DATA, "wrong return val\n"); - ok( !strcmp(buffer,"xy"), "buffer was not changed\n"); - ok( sz == 3, "wrong size returned\n"); - - r = MsiSetPropertyA(hpkg, "SourceDir", "foo"); - ok( r == ERROR_SUCCESS, "wrong return val\n"); + ok(r == ERROR_MORE_DATA, "got %u\n", r); + ok(!strcmp(buffer,"xy"), "got "%s"\n", buffer); + ok(sz == 3, "got size %u\n", sz);
sz = 4; - r = MsiGetPropertyA(hpkg, "SOURCEDIR", buffer, &sz); - ok( r == ERROR_SUCCESS, "wrong return val\n"); - ok( !strcmp(buffer,""), "buffer wrong\n"); - ok( sz == 0, "wrong size returned\n"); + strcpy(buffer,"x"); + r = MsiGetPropertyA( hpkg, "boo", buffer, &sz ); + ok(!r, "got %u\n", r); + ok(!strcmp(buffer,"xyz"), "got "%s"\n", buffer); + ok(sz == 3, "got size %u\n", sz);
- sz = 4; - r = MsiGetPropertyA(hpkg, "SOMERANDOMNAME", buffer, &sz); - ok( r == ERROR_SUCCESS, "wrong return val\n"); - ok( !strcmp(buffer,""), "buffer wrong\n"); - ok( sz == 0, "wrong size returned\n"); + /* properties are case-sensitive */ + check_prop(hpkg, "BOO", "");
- sz = 4; - r = MsiGetPropertyA(hpkg, "SourceDir", buffer, &sz); - ok( r == ERROR_SUCCESS, "wrong return val\n"); - ok( !strcmp(buffer,"foo"), "buffer wrong\n"); - ok( sz == 3, "wrong size returned\n"); - - r = MsiSetPropertyA(hpkg, "MetadataCompName", "Photoshop.dll"); - ok( r == ERROR_SUCCESS, "wrong return val\n"); - - sz = 0; - r = MsiGetPropertyA(hpkg, "MetadataCompName", NULL, &sz ); - ok( r == ERROR_SUCCESS, "return wrong\n"); - ok( sz == 13, "size wrong (%d)\n", sz); - - sz = 13; - r = MsiGetPropertyA(hpkg, "MetadataCompName", buffer, &sz ); - ok( r == ERROR_MORE_DATA, "return wrong\n"); - ok( !strcmp(buffer,"Photoshop.dl"), "buffer wrong\n"); - - r = MsiSetPropertyA(hpkg, "property", "value"); - ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); - - sz = 6; - r = MsiGetPropertyA(hpkg, "property", buffer, &sz); - ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); - ok( !strcmp(buffer, "value"), "Expected value, got %s\n", buffer); - - r = MsiSetPropertyA(hpkg, "property", NULL); - ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); - - sz = 6; - r = MsiGetPropertyA(hpkg, "property", buffer, &sz); - ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); - ok(!buffer[0], "Expected empty string, got %s\n", buffer); + /* properties set in Property table should work */ + check_prop(hpkg, "MetadataCompName", "Photoshop.dll");
MsiCloseHandle( hpkg ); DeleteFileA(msifile); @@ -3779,57 +3747,6 @@ static void test_states(void) DeleteFileA(msifile4); }
-static void test_getproperty(void) -{ - MSIHANDLE hPackage = 0; - char prop[100]; - static CHAR empty[] = ""; - DWORD size; - UINT r; - - r = package_from_db(create_package_db(), &hPackage); - if (r == ERROR_INSTALL_PACKAGE_REJECTED) - { - skip("Not enough rights to perform tests\n"); - DeleteFileA(msifile); - return; - } - ok( r == ERROR_SUCCESS, "Failed to create package %u\n", r ); - - /* set the property */ - r = MsiSetPropertyA(hPackage, "Name", "Value"); - ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); - - /* retrieve the size, NULL pointer */ - size = 0; - r = MsiGetPropertyA(hPackage, "Name", NULL, &size); - ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); - ok( size == 5, "Expected 5, got %d\n", size); - - /* retrieve the size, empty string */ - size = 0; - r = MsiGetPropertyA(hPackage, "Name", empty, &size); - ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r); - ok( size == 5, "Expected 5, got %d\n", size); - - /* don't change size */ - r = MsiGetPropertyA(hPackage, "Name", prop, &size); - ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r); - ok( size == 5, "Expected 5, got %d\n", size); - ok( !lstrcmpA(prop, "Valu"), "Expected Valu, got %s\n", prop); - - /* increase the size by 1 */ - size++; - r = MsiGetPropertyA(hPackage, "Name", prop, &size); - ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); - ok( size == 5, "Expected 5, got %d\n", size); - ok( !lstrcmpA(prop, "Value"), "Expected Value, got %s\n", prop); - - r = MsiCloseHandle( hPackage); - ok( r == ERROR_SUCCESS , "Failed to close package\n" ); - DeleteFileA(msifile); -} - static void test_removefiles(void) { MSIHANDLE hpkg; @@ -9723,7 +9640,6 @@ START_TEST(package) test_formatrecord2(); test_formatrecord_tables(); test_states(); - test_getproperty(); test_removefiles(); test_appsearch(); test_appsearch_complocator();
Signed-off-by: Hans Leidekker hans@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/msi/install.c | 4 ++++ dlls/msi/tests/package.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+)
diff --git a/dlls/msi/install.c b/dlls/msi/install.c index 65840e2..814addc 100644 --- a/dlls/msi/install.c +++ b/dlls/msi/install.c @@ -180,7 +180,11 @@ UINT msi_strcpy_to_awstring( const WCHAR *str, int len, awstring *awbuf, DWORD * if (len < 0) len = strlenW( str );
if (awbuf->unicode && awbuf->str.w) + { memcpy( awbuf->str.w, str, min(len + 1, *sz) * sizeof(WCHAR) ); + if (*sz && len >= *sz) + awbuf->str.w[*sz - 1] = 0; + } else { int lenA = WideCharToMultiByte( CP_ACP, 0, str, len + 1, NULL, 0, NULL, NULL ); diff --git a/dlls/msi/tests/package.c b/dlls/msi/tests/package.c index 6414891..b85a3a8 100644 --- a/dlls/msi/tests/package.c +++ b/dlls/msi/tests/package.c @@ -2150,10 +2150,14 @@ static void check_prop(MSIHANDLE hpkg, const char *prop, const char *expect)
static void test_props(void) { + static const WCHAR booW[] = {'b','o','o',0}; + static const WCHAR xyzW[] = {'x','y','z',0}; + static const WCHAR xyW[] = {'x','y',0}; MSIHANDLE hpkg, hdb; UINT r; DWORD sz; char buffer[0x100]; + WCHAR bufferW[10];
hdb = create_package_db();
@@ -2280,6 +2284,39 @@ static void test_props(void) ok(!strcmp(buffer,"xyz"), "got "%s"\n", buffer); ok(sz == 3, "got size %u\n", sz);
+ sz = 0; + r = MsiGetPropertyW(hpkg, booW, NULL, &sz); + ok(!r, "got %u\n", r); + ok(sz == 3, "got size %u\n", sz); + + sz = 0; + lstrcpyW(bufferW, booW); + r = MsiGetPropertyW(hpkg, booW, bufferW, &sz); + ok(r == ERROR_MORE_DATA, "got %u\n", r); + ok(!lstrcmpW(bufferW, booW), "got %s\n", wine_dbgstr_w(bufferW)); + ok(sz == 3, "got size %u\n", sz); + + sz = 1; + lstrcpyW(bufferW, booW); + r = MsiGetPropertyW(hpkg, booW, bufferW, &sz ); + ok(r == ERROR_MORE_DATA, "got %u\n", r); + ok(!bufferW[0], "got %s\n", wine_dbgstr_w(bufferW)); + ok(sz == 3, "got size %u\n", sz); + + sz = 3; + lstrcpyW(bufferW, booW); + r = MsiGetPropertyW(hpkg, booW, bufferW, &sz ); + ok(r == ERROR_MORE_DATA, "got %u\n", r); + ok(!lstrcmpW(bufferW, xyW), "got %s\n", wine_dbgstr_w(bufferW)); + ok(sz == 3, "got size %u\n", sz); + + sz = 4; + lstrcpyW(bufferW, booW); + r = MsiGetPropertyW(hpkg, booW, bufferW, &sz ); + ok(!r, "got %u\n", r); + ok(!lstrcmpW(bufferW, xyzW), "got %s\n", wine_dbgstr_w(bufferW)); + ok(sz == 3, "got size %u\n", sz); + /* properties are case-sensitive */ check_prop(hpkg, "BOO", "");
Signed-off-by: Hans Leidekker hans@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- v2: test embedded nulls
dlls/msi/tests/custom.c | 192 +++++++++++++++++++++++++++++++++++++++++++++++ dlls/msi/tests/install.c | 2 + 2 files changed, 194 insertions(+)
diff --git a/dlls/msi/tests/custom.c b/dlls/msi/tests/custom.c index feb8061..9cf90dc 100644 --- a/dlls/msi/tests/custom.c +++ b/dlls/msi/tests/custom.c @@ -51,6 +51,196 @@ static void ok_(MSIHANDLE hinst, int todo, const char *file, int line, int condi #define ok(hinst, condition, ...) ok_(hinst, 0, __FILE__, __LINE__, condition, __VA_ARGS__) #define todo_wine_ok(hinst, condition, ...) ok_(hinst, 1, __FILE__, __LINE__, condition, __VA_ARGS__)
+static const char *dbgstr_w(WCHAR *str) +{ + static char buffer[300], *p; + + if (!str) return "(null)"; + + p = buffer; + *p++ = 'L'; + *p++ = '"'; + while ((*p++ = *str++)); + *p++ = '"'; + *p++ = 0; + + return buffer; +} + +static void check_prop(MSIHANDLE hinst, const char *prop, const char *expect) +{ + char buffer[10] = "x"; + DWORD sz = sizeof(buffer); + UINT r = MsiGetPropertyA(hinst, prop, buffer, &sz); + ok(hinst, !r, "'%s': got %u\n", prop, r); + ok(hinst, sz == strlen(buffer), "'%s': expected %u, got %u\n", prop, strlen(buffer), sz); + ok(hinst, !strcmp(buffer, expect), "expected '%s', got '%s'\n", expect, buffer); +} + +static void test_props(MSIHANDLE hinst) +{ + static const WCHAR booW[] = {'b','o','o',0}; + static const WCHAR xyzW[] = {'x','y','z',0}; + static const WCHAR xyW[] = {'x','y',0}; + char buffer[10]; + WCHAR bufferW[10]; + DWORD sz; + UINT r; + + /* test invalid values */ + r = MsiGetPropertyA(hinst, NULL, NULL, NULL); + ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r); + + r = MsiGetPropertyA(hinst, "boo", NULL, NULL); + ok(hinst, !r, "got %u\n", r); + + r = MsiGetPropertyA(hinst, "boo", buffer, NULL ); + ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r); + + sz = 0; + r = MsiGetPropertyA(hinst, "boo", NULL, &sz); + ok(hinst, !r, "got %u\n", r); + ok(hinst, sz == 0, "got size %u\n", sz); + + sz = 0; + strcpy(buffer,"x"); + r = MsiGetPropertyA(hinst, "boo", buffer, &sz); + ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r); + ok(hinst, !strcmp(buffer, "x"), "got "%s"\n", buffer); + ok(hinst, sz == 0, "got size %u\n", sz); + + sz = 1; + strcpy(buffer,"x"); + r = MsiGetPropertyA(hinst, "boo", buffer, &sz); + ok(hinst, !r, "got %u\n", r); + ok(hinst, !buffer[0], "got "%s"\n", buffer); + ok(hinst, sz == 0, "got size %u\n", sz); + + /* set the property to something */ + r = MsiSetPropertyA(hinst, NULL, NULL); + ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r); + + r = MsiSetPropertyA(hinst, "", NULL); + ok(hinst, !r, "got %u\n", r); + + r = MsiSetPropertyA(hinst, "", "asdf"); + ok(hinst, r == ERROR_FUNCTION_FAILED, "got %u\n", r); + + r = MsiSetPropertyA(hinst, "=", "asdf"); + ok(hinst, !r, "got %u\n", r); + check_prop(hinst, "=", "asdf"); + + r = MsiSetPropertyA(hinst, " ", "asdf"); + ok(hinst, !r, "got %u\n", r); + check_prop(hinst, " ", "asdf"); + + r = MsiSetPropertyA(hinst, "'", "asdf"); + ok(hinst, !r, "got %u\n", r); + check_prop(hinst, "'", "asdf"); + + r = MsiSetPropertyA(hinst, "boo", NULL); + ok(hinst, !r, "got %u\n", r); + check_prop(hinst, "boo", ""); + + r = MsiSetPropertyA(hinst, "boo", ""); + ok(hinst, !r, "got %u\n", r); + check_prop(hinst, "boo", ""); + + r = MsiSetPropertyA(hinst, "boo", "xyz"); + ok(hinst, !r, "got %u\n", r); + check_prop(hinst, "boo", "xyz"); + + r = MsiGetPropertyA(hinst, "boo", NULL, NULL); + ok(hinst, !r, "got %u\n", r); + + r = MsiGetPropertyA(hinst, "boo", 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 = MsiGetPropertyA(hinst, "boo", NULL, &sz); + ok(hinst, !r, "got %u\n", r); + ok(hinst, sz == 6, "got size %u\n", sz); + + sz = 0; + strcpy(buffer,"q"); + r = MsiGetPropertyA(hinst, "boo", 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 = MsiGetPropertyA(hinst, "boo", 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 = MsiGetPropertyA(hinst, "boo", buffer, &sz); + ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r); + ok(hinst, !strcmp(buffer, "xy"), "got "%s"\n", buffer); + todo_wine_ok(hinst, sz == 6, "got size %u\n", sz); + + sz = 4; + strcpy(buffer,"x"); + r = MsiGetPropertyA(hinst, "boo", buffer, &sz); + ok(hinst, !r, "got %u\n", r); + ok(hinst, !strcmp(buffer, "xyz"), "got "%s"\n", buffer); + ok(hinst, sz == 3, "got size %u\n", sz); + + sz = 0; + r = MsiGetPropertyW(hinst, booW, NULL, &sz); + ok(hinst, !r, "got %u\n", r); + ok(hinst, sz == 3, "got size %u\n", sz); + + sz = 0; + lstrcpyW(bufferW, booW); + r = MsiGetPropertyW(hinst, booW, bufferW, &sz); + ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r); + ok(hinst, !lstrcmpW(bufferW, booW), "got %s\n", dbgstr_w(bufferW)); + ok(hinst, sz == 3, "got size %u\n", sz); + + sz = 1; + lstrcpyW(bufferW, booW); + r = MsiGetPropertyW(hinst, booW, 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; + lstrcpyW(bufferW, booW); + r = MsiGetPropertyW(hinst, booW, 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; + lstrcpyW(bufferW, booW); + r = MsiGetPropertyW(hinst, booW, 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); + + r = MsiSetPropertyA(hinst, "boo", NULL); + ok(hinst, !r, "got %u\n", r); + check_prop(hinst, "boo", ""); + + sz = 0; + r = MsiGetPropertyA(hinst, "embednullprop", NULL, &sz); + ok(hinst, !r, "got %u\n", r); + ok(hinst, sz == 6, "got size %u\n", sz); + + sz = 4; + memset(buffer, 0xcc, sizeof(buffer)); + r = MsiGetPropertyA(hinst, "embednullprop", buffer, &sz); + ok(hinst, !r, "got %u\n", r); + ok(hinst, sz == 3, "got size %u\n", sz); + ok(hinst, !memcmp(buffer, "a\0\0\0\xcc", 5), "wrong data\n"); +}
/* Main test. Anything that doesn't depend on a specific install configuration * or have undesired side effects should go here. */ @@ -70,6 +260,8 @@ UINT WINAPI main_test(MSIHANDLE hinst) res = MsiGetDatabaseState(hinst); todo_wine_ok(hinst, res == MSIDBSTATE_ERROR, "expected MSIDBSTATE_ERROR, got %u\n", res);
+ test_props(hinst); + return ERROR_SUCCESS; }
diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c index 69095cd..62fb81f 100644 --- a/dlls/msi/tests/install.c +++ b/dlls/msi/tests/install.c @@ -695,12 +695,14 @@ 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" + "embednull\t\t600\n" "maintest\tMAIN_TEST\t700\n" "testretval\tTEST_RETVAL\t710\n";
static const CHAR ca1_custom_action_dat[] = "Action\tType\tSource\tTarget\n" "s72\ti2\tS64\tS0\n" "CustomAction\tAction\n" + "embednull\t51\tembednullprop\ta[~]b\n" "maintest\t1\tcustom.dll\tmain_test\n" "testretval\t1\tcustom.dll\ttest_retval\n";
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check? Full results can be found at https://testbot.winehq.org/JobDetails.pl?Key=37747
Your paranoid android.
=== w7pro64 (32 bit custom) === The previous 1 run(s) terminated abnormally
=== w7pro64 (64 bit custom) === The previous 1 run(s) terminated abnormally
Signed-off-by: Hans Leidekker hans@codeweavers.com