Commit 3e6f31bf authored by Mike McCormack's avatar Mike McCormack Committed by Alexandre Julliard

Fix and test MsiGetProperty and MsiSetProperty.

parent 94caa05d
......@@ -116,7 +116,7 @@ UINT WINAPI MsiSequenceW( MSIHANDLE hInstall, LPCWSTR szTable, INT iSequenceMode
return ret;
}
static UINT msi_strcpy_to_awstring( LPCWSTR str, awstring *awbuf, DWORD *sz )
UINT msi_strcpy_to_awstring( LPCWSTR str, awstring *awbuf, DWORD *sz )
{
UINT len, r = ERROR_SUCCESS;
......@@ -134,9 +134,12 @@ static UINT msi_strcpy_to_awstring( LPCWSTR str, awstring *awbuf, DWORD *sz )
}
else
{
len = WideCharToMultiByte( CP_ACP, 0, str, -1,
awbuf->str.a, *sz, NULL, NULL );
len--;
len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
if (len)
len--;
WideCharToMultiByte( CP_ACP, 0, str, -1, awbuf->str.a, *sz, NULL, NULL );
if ( *sz && (len >= *sz) )
awbuf->str.a[*sz - 1] = 0;
}
if (len >= *sz)
......
......@@ -254,6 +254,7 @@ DEFINE_GUID(CLSID_IMsiServerX3, 0x000C1094,0x0000,0x0000,0xC0,0x00,0x00,0x00,0x0
DEFINE_GUID(CLSID_IMsiServerMessage, 0x000C101D,0x0000,0x0000,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
/* handle unicode/ascii output in the Msi* API functions */
typedef struct {
BOOL unicode;
union {
......@@ -270,6 +271,8 @@ typedef struct {
} str;
} awcstring;
UINT msi_strcpy_to_awstring( LPCWSTR str, awstring *awbuf, DWORD *sz );
/* handle functions */
extern void *msihandle2msiinfo(MSIHANDLE handle, UINT type);
extern MSIHANDLE alloc_msihandle( MSIOBJECTHDR * );
......
......@@ -682,32 +682,26 @@ out:
}
/* property code */
UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue)
UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue )
{
LPWSTR szwName = NULL, szwValue = NULL;
UINT hr = ERROR_INSTALL_FAILURE;
UINT r = ERROR_OUTOFMEMORY;
if( szName )
{
szwName = strdupAtoW( szName );
if( !szwName )
goto end;
}
szwName = strdupAtoW( szName );
if( szName && !szwName )
goto end;
if( szValue )
{
szwValue = strdupAtoW( szValue );
if( !szwValue)
goto end;
}
szwValue = strdupAtoW( szValue );
if( szValue && !szwValue )
goto end;
hr = MsiSetPropertyW( hInstall, szwName, szwValue);
r = MsiSetPropertyW( hInstall, szwName, szwValue);
end:
msi_free( szwName );
msi_free( szwValue );
return hr;
return r;
}
UINT MSI_SetPropertyW( MSIPACKAGE *package, LPCWSTR szName, LPCWSTR szValue)
......@@ -728,8 +722,14 @@ UINT MSI_SetPropertyW( MSIPACKAGE *package, LPCWSTR szName, LPCWSTR szValue)
,'e','r','t','y','`',' ','=',' ','\'','%','s','\'',0};
WCHAR Query[1024];
TRACE("Setting property (%s %s)\n",debugstr_w(szName),
debugstr_w(szValue));
TRACE("%p %s %s\n", package, debugstr_w(szName), debugstr_w(szValue));
if (!szName)
return ERROR_INVALID_PARAMETER;
/* this one is wierd... */
if (!szName[0])
return szValue ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS;
rc = MSI_GetPropertyW(package,szName,0,&sz);
if (rc==ERROR_MORE_DATA || rc == ERROR_SUCCESS)
......@@ -767,11 +767,6 @@ UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue
MSIPACKAGE *package;
UINT ret;
if (NULL == szName)
return ERROR_INVALID_PARAMETER;
if (NULL == szValue)
return ERROR_INVALID_PARAMETER;
package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
if( !package )
return ERROR_INVALID_HANDLE;
......@@ -780,51 +775,33 @@ UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue
return ret;
}
static UINT MSI_GetPropertyRow(MSIPACKAGE *package, LPCWSTR szName, MSIRECORD **row)
static MSIRECORD *MSI_GetPropertyRow( MSIPACKAGE *package, LPCWSTR name )
{
MSIQUERY *view;
UINT rc, sz;
static const WCHAR select[]=
static const WCHAR query[]=
{'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ',
'F','R','O','M',' ' ,'`','_','P','r','o','p','e','r','t','y','`',
' ','W','H','E','R','E',' ' ,'`','_','P','r','o','p','e','r','t','y','`',
'=','\'','%','s','\'',0};
LPWSTR query;
if (!szName)
return ERROR_INVALID_PARAMETER;
sz = sizeof select + strlenW(szName)*sizeof(WCHAR);
query = msi_alloc( sz);
sprintfW(query,select,szName);
rc = MSI_DatabaseOpenViewW(package->db, query, &view);
msi_free(query);
if (rc == ERROR_SUCCESS)
{
rc = MSI_ViewExecute(view, 0);
if (rc == ERROR_SUCCESS)
rc = MSI_ViewFetch(view,row);
MSI_ViewClose(view);
msiobj_release(&view->hdr);
}
if (!name || !name[0])
return NULL;
return rc;
return MSI_QueryGetRecord( package->db, query, name );
}
UINT MSI_GetPropertyW(MSIPACKAGE *package, LPCWSTR szName,
LPWSTR szValueBuf, DWORD* pchValueBuf)
/* internal function, not compatible with MsiGetPropertyW */
UINT MSI_GetPropertyW( MSIPACKAGE *package, LPCWSTR szName,
LPWSTR szValueBuf, DWORD* pchValueBuf )
{
MSIRECORD *row;
UINT rc;
UINT rc = ERROR_FUNCTION_FAILED;
rc = MSI_GetPropertyRow(package, szName, &row);
row = MSI_GetPropertyRow( package, szName );
if (*pchValueBuf > 0)
szValueBuf[0] = 0;
if (rc == ERROR_SUCCESS)
if (row)
{
rc = MSI_RecordGetStringW(row,1,szValueBuf,pchValueBuf);
msiobj_release(&row->hdr);
......@@ -845,106 +822,67 @@ UINT MSI_GetPropertyW(MSIPACKAGE *package, LPCWSTR szName,
return rc;
}
UINT MSI_GetPropertyA(MSIPACKAGE *package, LPCSTR szName,
LPSTR szValueBuf, DWORD* pchValueBuf)
{
MSIRECORD *row;
UINT rc;
LPWSTR szwName = NULL;
if (*pchValueBuf > 0)
szValueBuf[0] = 0;
if( szName )
{
szwName = strdupAtoW( szName );
if (!szwName)
return ERROR_NOT_ENOUGH_MEMORY;
}
rc = MSI_GetPropertyRow(package, szwName, &row);
if (rc == ERROR_SUCCESS)
{
rc = MSI_RecordGetStringA(row,1,szValueBuf,pchValueBuf);
msiobj_release(&row->hdr);
}
if (rc == ERROR_SUCCESS)
TRACE("returning %s for property %s\n", debugstr_a(szValueBuf),
debugstr_a(szName));
else if (rc == ERROR_MORE_DATA)
TRACE("need %ld sized buffer for %s\n", *pchValueBuf,
debugstr_a(szName));
else
{
*pchValueBuf = 0;
TRACE("property not found\n");
}
msi_free( szwName );
return rc;
}
UINT WINAPI MsiGetPropertyA(MSIHANDLE hInstall, LPCSTR szName, LPSTR szValueBuf, DWORD* pchValueBuf)
static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name,
awstring *szValueBuf, DWORD* pchValueBuf )
{
static const WCHAR empty[] = {0};
MSIPACKAGE *package;
UINT ret;
MSIRECORD *row = NULL;
UINT r;
LPCWSTR val = NULL;
TRACE("%lu %s %p\n", hInstall, debugstr_a(szName), pchValueBuf);
TRACE("%lu %s %p %p\n", handle, debugstr_w(name),
szValueBuf->str.w, pchValueBuf );
if (0 == hInstall)
return ERROR_INVALID_HANDLE;
if (NULL == szName)
if (!name)
return ERROR_INVALID_PARAMETER;
if (NULL != szValueBuf && NULL == pchValueBuf)
return ERROR_INVALID_PARAMETER;
/* This was tested against native msi */
if (NULL == szValueBuf && NULL != pchValueBuf)
*pchValueBuf = 0;
package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE );
if (!package)
return ERROR_INVALID_HANDLE;
ret = MSI_GetPropertyA(package, szName, szValueBuf, pchValueBuf );
msiobj_release( &package->hdr );
/* MsiGetProperty does not return error codes on missing properties */
if (ret != ERROR_MORE_DATA)
ret = ERROR_SUCCESS;
row = MSI_GetPropertyRow( package, name );
if (row)
val = MSI_RecordGetString( row, 1 );
return ret;
if (!val)
val = empty;
r = msi_strcpy_to_awstring( val, szValueBuf, pchValueBuf );
if (row)
msiobj_release( &row->hdr );
msiobj_release( &package->hdr );
return r;
}
UINT WINAPI MsiGetPropertyW(MSIHANDLE hInstall, LPCWSTR szName,
LPWSTR szValueBuf, DWORD* pchValueBuf)
UINT WINAPI MsiGetPropertyA( MSIHANDLE hInstall, LPCSTR szName,
LPSTR szValueBuf, DWORD* pchValueBuf )
{
MSIPACKAGE *package;
UINT ret;
TRACE("%lu %s %p\n", hInstall, debugstr_w(szName), pchValueBuf);
awstring val;
LPWSTR name;
UINT r;
if (0 == hInstall)
return ERROR_INVALID_HANDLE;
if (NULL == szName)
return ERROR_INVALID_PARAMETER;
if (NULL != szValueBuf && NULL == pchValueBuf)
return ERROR_INVALID_PARAMETER;
val.unicode = FALSE;
val.str.a = szValueBuf;
/* This was tested against native msi */
if (NULL == szValueBuf && NULL != pchValueBuf)
*pchValueBuf = 0;
name = strdupAtoW( szName );
if (szName && !name)
return ERROR_OUTOFMEMORY;
package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
if (!package)
return ERROR_INVALID_HANDLE;
ret = MSI_GetPropertyW(package, szName, szValueBuf, pchValueBuf );
msiobj_release( &package->hdr );
r = MSI_GetProperty( hInstall, name, &val, pchValueBuf );
msi_free( name );
return r;
}
UINT WINAPI MsiGetPropertyW( MSIHANDLE hInstall, LPCWSTR szName,
LPWSTR szValueBuf, DWORD* pchValueBuf )
{
awstring val;
/* MsiGetProperty does not return error codes on missing properties */
if (ret != ERROR_MORE_DATA)
ret = ERROR_SUCCESS;
val.unicode = TRUE;
val.str.w = szValueBuf;
return ret;
return MSI_GetProperty( hInstall, szName, &val, pchValueBuf );
}
......@@ -567,6 +567,128 @@ void test_condition(void)
MsiCloseHandle( hpkg );
}
static BOOL check_prop_empty( MSIHANDLE hpkg, char * prop)
{
UINT r;
DWORD sz;
char buffer[2];
sz = sizeof buffer;
strcpy(buffer,"x");
r = MsiGetProperty( hpkg, prop, buffer, &sz );
return r == ERROR_SUCCESS && buffer[0] == 0 && sz == 0;
}
static void test_props(void)
{
MSIHANDLE hpkg;
UINT r;
DWORD sz;
char buffer[0x100];
hpkg = package_from_db(create_package_db());
ok( hpkg, "failed to create package\n");
/* test invalid values */
r = MsiGetProperty( 0, NULL, NULL, NULL );
ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
r = MsiGetProperty( hpkg, NULL, NULL, NULL );
ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
r = MsiGetProperty( hpkg, "boo", NULL, NULL );
ok( r == ERROR_SUCCESS, "wrong return val\n");
r = MsiGetProperty( hpkg, "boo", buffer, NULL );
ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
/* test retrieving an empty/non-existant property */
sz = sizeof buffer;
r = MsiGetProperty( hpkg, "boo", NULL, &sz );
ok( r == ERROR_SUCCESS, "wrong return val\n");
ok( sz == 0, "wrong size returned\n");
check_prop_empty( hpkg, "boo");
sz = 0;
strcpy(buffer,"x");
r = MsiGetProperty( 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");
sz = 1;
strcpy(buffer,"x");
r = MsiGetProperty( 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");
/* set the property to something */
r = MsiSetProperty( 0, NULL, NULL );
ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
r = MsiSetProperty( hpkg, NULL, NULL );
ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
r = MsiSetProperty( hpkg, "", NULL );
ok( r == ERROR_SUCCESS, "wrong return val\n");
/* try set and get some illegal property identifiers */
r = MsiSetProperty( hpkg, "", "asdf" );
ok( r == ERROR_FUNCTION_FAILED, "wrong return val\n");
r = MsiSetProperty( hpkg, "=", "asdf" );
ok( r == ERROR_SUCCESS, "wrong return val\n");
r = MsiSetProperty( hpkg, " ", "asdf" );
ok( r == ERROR_SUCCESS, "wrong return val\n");
r = MsiSetProperty( hpkg, "'", "asdf" );
ok( r == ERROR_SUCCESS, "wrong return val\n");
sz = sizeof buffer;
buffer[0]=0;
r = MsiGetProperty( hpkg, "'", buffer, &sz );
ok( r == ERROR_SUCCESS, "wrong return val\n");
ok( !strcmp(buffer,"asdf"), "buffer was not changed\n");
/* set empty values */
r = MsiSetProperty( hpkg, "boo", NULL );
ok( r == ERROR_SUCCESS, "wrong return val\n");
ok( check_prop_empty( hpkg, "boo"), "prop wasn't empty\n");
r = MsiSetProperty( hpkg, "boo", "" );
ok( r == ERROR_SUCCESS, "wrong return val\n");
ok( check_prop_empty( hpkg, "boo"), "prop wasn't empty\n");
/* set a non-empty value */
r = MsiSetProperty( hpkg, "boo", "xyz" );
ok( r == ERROR_SUCCESS, "wrong return val\n");
sz = 1;
strcpy(buffer,"x");
r = MsiGetProperty( 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 = MsiGetProperty( 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");
sz = 3;
strcpy(buffer,"x");
r = MsiGetProperty( 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");
MsiCloseHandle( hpkg );
}
START_TEST(package)
{
test_createpackage();
......@@ -574,4 +696,5 @@ START_TEST(package)
test_getsourcepath();
test_doaction();
test_gettargetpath_bad();
test_props();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment