forked from Mirrors/wine-wine
msi: Add a partial implementation of MsiProvideComponent.
parent
b24b8a507f
commit
a884d98e99
|
@ -4198,6 +4198,92 @@ UINT WINAPI MsiInstallMissingComponentW(LPCWSTR szProduct, LPCWSTR szComponent,
|
||||||
return ERROR_SUCCESS;
|
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.@]
|
* MsiBeginTransactionA [MSI.@]
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -97,10 +97,10 @@
|
||||||
101 stub MsiProcessAdvertiseScriptA
|
101 stub MsiProcessAdvertiseScriptA
|
||||||
102 stub MsiProcessAdvertiseScriptW
|
102 stub MsiProcessAdvertiseScriptW
|
||||||
103 stdcall MsiProcessMessage(long long long)
|
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)
|
105 stdcall MsiProvideComponentFromDescriptorA(str ptr ptr ptr)
|
||||||
106 stdcall MsiProvideComponentFromDescriptorW(wstr 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)
|
108 stdcall MsiProvideQualifiedComponentA(str str long ptr ptr)
|
||||||
109 stdcall MsiProvideQualifiedComponentW(wstr wstr long ptr ptr)
|
109 stdcall MsiProvideQualifiedComponentW(wstr wstr long ptr ptr)
|
||||||
110 stdcall MsiQueryFeatureStateA(str str)
|
110 stdcall MsiQueryFeatureStateA(str str)
|
||||||
|
|
|
@ -50,6 +50,10 @@ static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
|
||||||
|
|
||||||
static INSTALLSTATE (WINAPI *pMsiGetComponentPathA)
|
static INSTALLSTATE (WINAPI *pMsiGetComponentPathA)
|
||||||
(LPCSTR, LPCSTR, LPSTR, DWORD*);
|
(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)
|
static UINT (WINAPI *pMsiGetFileHashA)
|
||||||
(LPCSTR, DWORD, PMSIFILEHASHINFO);
|
(LPCSTR, DWORD, PMSIFILEHASHINFO);
|
||||||
static UINT (WINAPI *pMsiGetProductInfoExA)
|
static UINT (WINAPI *pMsiGetProductInfoExA)
|
||||||
|
@ -88,6 +92,8 @@ static void init_functionpointers(void)
|
||||||
trace("GetProcAddress(%s) failed\n", #func);
|
trace("GetProcAddress(%s) failed\n", #func);
|
||||||
|
|
||||||
GET_PROC(hmsi, MsiGetComponentPathA)
|
GET_PROC(hmsi, MsiGetComponentPathA)
|
||||||
|
GET_PROC(hmsi, MsiProvideComponentA)
|
||||||
|
GET_PROC(hmsi, MsiProvideComponentW)
|
||||||
GET_PROC(hmsi, MsiGetFileHashA)
|
GET_PROC(hmsi, MsiGetFileHashA)
|
||||||
GET_PROC(hmsi, MsiGetProductInfoExA)
|
GET_PROC(hmsi, MsiGetProductInfoExA)
|
||||||
GET_PROC(hmsi, MsiOpenPackageExA)
|
GET_PROC(hmsi, MsiOpenPackageExA)
|
||||||
|
@ -3404,6 +3410,100 @@ static void test_MsiGetComponentPath(void)
|
||||||
LocalFree(usersid);
|
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)
|
static void test_MsiGetProductCode(void)
|
||||||
{
|
{
|
||||||
HKEY compkey, prodkey;
|
HKEY compkey, prodkey;
|
||||||
|
@ -14300,6 +14400,7 @@ START_TEST(msi)
|
||||||
test_MsiQueryFeatureState();
|
test_MsiQueryFeatureState();
|
||||||
test_MsiQueryComponentState();
|
test_MsiQueryComponentState();
|
||||||
test_MsiGetComponentPath();
|
test_MsiGetComponentPath();
|
||||||
|
test_MsiProvideComponent();
|
||||||
test_MsiGetProductCode();
|
test_MsiGetProductCode();
|
||||||
test_MsiEnumClients();
|
test_MsiEnumClients();
|
||||||
test_MsiGetProductInfo();
|
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);
|
USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR, LPWSTR, LPDWORD, LPWSTR, LPDWORD, LPWSTR, LPDWORD);
|
||||||
#define MsiGetUserInfo WINELIB_NAME_AW(MsiGetUserInfo)
|
#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 MsiCollectUserInfoA(LPCSTR);
|
||||||
UINT WINAPI MsiCollectUserInfoW(LPCWSTR);
|
UINT WINAPI MsiCollectUserInfoW(LPCWSTR);
|
||||||
#define MsiCollectUserInfo WINELIB_NAME_AW(MsiCollectUserInfo)
|
#define MsiCollectUserInfo WINELIB_NAME_AW(MsiCollectUserInfo)
|
||||||
|
|
Loading…
Reference in New Issue