Commit a884d98e authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

msi: Add a partial implementation of MsiProvideComponent.

parent b24b8a50
......@@ -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.@]
*/
......
......@@ -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)
......
......@@ -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();
......
......@@ -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)
......
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