msi: Add a partial implementation of MsiProvideComponent.

This commit is contained in:
Hans Leidekker 2015-01-21 13:26:31 +01:00 committed by Alexandre Julliard
parent b24b8a507f
commit a884d98e99
4 changed files with 193 additions and 2 deletions

View File

@ -4198,6 +4198,92 @@ UINT WINAPI MsiInstallMissingComponentW(LPCWSTR szProduct, LPCWSTR szComponent,
return ERROR_SUCCESS;
}
UINT WINAPI MsiProvideComponentA( LPCSTR product, LPCSTR feature, LPCSTR component, DWORD mode, LPSTR buf, LPDWORD buflen )
{
WCHAR *productW = NULL, *componentW = NULL, *featureW = NULL, *bufW = NULL;
UINT r = ERROR_OUTOFMEMORY;
DWORD lenW;
int len;
TRACE("%s, %s, %s, %x, %p, %p\n", debugstr_a(product), debugstr_a(component), debugstr_a(feature), mode, buf, buflen);
if (product && !(productW = strdupAtoW( product ))) goto done;
if (feature && !(featureW = strdupAtoW( feature ))) goto done;
if (component && !(componentW = strdupAtoW( component ))) goto done;
r = MsiProvideComponentW( productW, featureW, componentW, mode, NULL, &lenW );
if (r != ERROR_SUCCESS)
goto done;
if (!(bufW = msi_alloc( ++lenW * sizeof(WCHAR) )))
{
r = ERROR_OUTOFMEMORY;
goto done;
}
r = MsiProvideComponentW( productW, featureW, componentW, mode, bufW, &lenW );
if (r != ERROR_SUCCESS)
goto done;
len = WideCharToMultiByte( CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL );
if (buf)
{
if (len > *buflen)
r = ERROR_MORE_DATA;
else
WideCharToMultiByte( CP_ACP, 0, bufW, -1, buf, *buflen, NULL, NULL );
}
*buflen = len - 1;
done:
msi_free( productW );
msi_free( featureW );
msi_free( componentW );
msi_free( bufW );
return r;
}
UINT WINAPI MsiProvideComponentW( LPCWSTR product, LPCWSTR feature, LPCWSTR component, DWORD mode, LPWSTR buf, LPDWORD buflen )
{
INSTALLSTATE state;
TRACE("%s, %s, %s, %x, %p, %p\n", debugstr_w(product), debugstr_w(component), debugstr_w(feature), mode, buf, buflen);
state = MsiQueryFeatureStateW( product, feature );
TRACE("feature state: %d\n", state);
switch (mode)
{
case INSTALLMODE_NODETECTION:
break;
default:
FIXME("mode %x not implemented\n", mode);
return ERROR_INSTALL_FAILURE;
}
state = MsiGetComponentPathW( product, component, buf, buflen );
TRACE("component state: %d\n", state);
switch (state)
{
case INSTALLSTATE_INVALIDARG:
return ERROR_INVALID_PARAMETER;
case INSTALLSTATE_MOREDATA:
return ERROR_MORE_DATA;
case INSTALLSTATE_ADVERTISED:
case INSTALLSTATE_LOCAL:
case INSTALLSTATE_SOURCE:
MsiUseFeatureW( product, feature );
return ERROR_SUCCESS;
default:
TRACE("MsiGetComponentPathW returned %d\n", state);
return ERROR_INSTALL_FAILURE;
}
}
/***********************************************************************
* MsiBeginTransactionA [MSI.@]
*/

View File

@ -97,10 +97,10 @@
101 stub MsiProcessAdvertiseScriptA
102 stub MsiProcessAdvertiseScriptW
103 stdcall MsiProcessMessage(long long long)
104 stub MsiProvideComponentA
104 stdcall MsiProvideComponentA(str str str long ptr ptr)
105 stdcall MsiProvideComponentFromDescriptorA(str ptr ptr ptr)
106 stdcall MsiProvideComponentFromDescriptorW(wstr ptr ptr ptr)
107 stub MsiProvideComponentW
107 stdcall MsiProvideComponentW(wstr wstr wstr long ptr ptr)
108 stdcall MsiProvideQualifiedComponentA(str str long ptr ptr)
109 stdcall MsiProvideQualifiedComponentW(wstr wstr long ptr ptr)
110 stdcall MsiQueryFeatureStateA(str str)

View File

@ -50,6 +50,10 @@ static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
static INSTALLSTATE (WINAPI *pMsiGetComponentPathA)
(LPCSTR, LPCSTR, LPSTR, DWORD*);
static INSTALLSTATE (WINAPI *pMsiProvideComponentA)
(LPCSTR, LPCSTR, LPCSTR, DWORD, LPSTR, LPDWORD);
static INSTALLSTATE (WINAPI *pMsiProvideComponentW)
(LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPWSTR, LPDWORD);
static UINT (WINAPI *pMsiGetFileHashA)
(LPCSTR, DWORD, PMSIFILEHASHINFO);
static UINT (WINAPI *pMsiGetProductInfoExA)
@ -88,6 +92,8 @@ static void init_functionpointers(void)
trace("GetProcAddress(%s) failed\n", #func);
GET_PROC(hmsi, MsiGetComponentPathA)
GET_PROC(hmsi, MsiProvideComponentA)
GET_PROC(hmsi, MsiProvideComponentW)
GET_PROC(hmsi, MsiGetFileHashA)
GET_PROC(hmsi, MsiGetProductInfoExA)
GET_PROC(hmsi, MsiOpenPackageExA)
@ -3404,6 +3410,100 @@ static void test_MsiGetComponentPath(void)
LocalFree(usersid);
}
static void test_MsiProvideComponent(void)
{
static const WCHAR sourcedirW[] =
{'s','o','u','r','c','e','d','i','r',0};
static const WCHAR productW[] =
{'{','3','8','8','4','7','3','3','8','-','1','B','B','C','-','4','1','0','4','-',
'8','1','A','C','-','2','F','A','A','C','7','E','C','D','D','C','D','}',0};
static const WCHAR componentW[] =
{'{','D','D','4','2','2','F','9','2','-','3','E','D','8','-','4','9','B','5','-',
'A','0','B','7','-','F','2','6','6','F','9','8','3','5','7','D','F','}',0};
INSTALLSTATE state;
char buf[0x100];
WCHAR bufW[0x100];
DWORD len, len2;
UINT r;
if (is_process_limited())
{
skip("process is limited\n");
return;
}
create_test_files();
create_file("msitest\\sourcedir.txt", "msitest\\sourcedir.txt", 1000);
create_database(msifile, sd_tables, sizeof(sd_tables) / sizeof(msi_table));
MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
buf[0] = 0;
len = sizeof(buf);
r = pMsiProvideComponentA("{90120000-0070-0000-0000-4000000FF1CE}",
"{17961602-C4E2-482E-800A-DF6E627549CF}",
"ProductFiles", INSTALLMODE_NODETECTION, buf, &len);
ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
r = MsiInstallProductA(msifile, NULL);
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
state = MsiQueryFeatureStateA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir");
ok(state == INSTALLSTATE_LOCAL, "got %d\n", state);
buf[0] = 0;
len = sizeof(buf);
r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir",
"{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
INSTALLMODE_NODETECTION, buf, &len);
ok(r == ERROR_SUCCESS, "got %u\n", r);
ok(buf[0], "empty path\n");
ok(len == lstrlenA(buf), "got %u\n", len);
len2 = 0;
r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir",
"{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
INSTALLMODE_NODETECTION, NULL, &len2);
ok(r == ERROR_SUCCESS, "got %u\n", r);
ok(len2 == len, "got %u\n", len2);
len2 = 0;
r = pMsiProvideComponentA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", "sourcedir",
"{DD422F92-3ED8-49B5-A0B7-F266F98357DF}",
INSTALLMODE_NODETECTION, buf, &len2);
ok(r == ERROR_MORE_DATA, "got %u\n", r);
ok(len2 == len, "got %u\n", len2);
/* wide version */
bufW[0] = 0;
len = sizeof(buf);
r = pMsiProvideComponentW(productW, sourcedirW, componentW,
INSTALLMODE_NODETECTION, bufW, &len);
ok(r == ERROR_SUCCESS, "got %u\n", r);
ok(bufW[0], "empty path\n");
ok(len == lstrlenW(bufW), "got %u\n", len);
len2 = 0;
r = pMsiProvideComponentW(productW, sourcedirW, componentW,
INSTALLMODE_NODETECTION, NULL, &len2);
ok(r == ERROR_SUCCESS, "got %u\n", r);
ok(len2 == len, "got %u\n", len2);
len2 = 0;
r = pMsiProvideComponentW(productW, sourcedirW, componentW,
INSTALLMODE_NODETECTION, bufW, &len2);
ok(r == ERROR_MORE_DATA, "got %u\n", r);
ok(len2 == len, "got %u\n", len2);
r = MsiInstallProductA(msifile, "REMOVE=ALL");
ok(r == ERROR_SUCCESS, "got %u\n", r);
DeleteFileA("msitest\\sourcedir.txt");
delete_test_files();
DeleteFileA(msifile);
}
static void test_MsiGetProductCode(void)
{
HKEY compkey, prodkey;
@ -14300,6 +14400,7 @@ START_TEST(msi)
test_MsiQueryFeatureState();
test_MsiQueryComponentState();
test_MsiGetComponentPath();
test_MsiProvideComponent();
test_MsiGetProductCode();
test_MsiEnumClients();
test_MsiGetProductInfo();

View File

@ -583,6 +583,10 @@ USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR, LPSTR, LPDWORD, LPSTR, LPDWORD, LPS
USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR, LPWSTR, LPDWORD, LPWSTR, LPDWORD, LPWSTR, LPDWORD);
#define MsiGetUserInfo WINELIB_NAME_AW(MsiGetUserInfo)
UINT WINAPI MsiProvidedComponentA(LPCSTR, LPCSTR, LPCSTR, DWORD, LPSTR, LPDWORD);
UINT WINAPI MsiProvideComponentW(LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPWSTR, LPDWORD);
#define MsiProvideComponent WINELIB_NAME_AW(MsiProvideComponent)
UINT WINAPI MsiCollectUserInfoA(LPCSTR);
UINT WINAPI MsiCollectUserInfoW(LPCWSTR);
#define MsiCollectUserInfo WINELIB_NAME_AW(MsiCollectUserInfo)