msi: Add a partial implementation of MsiProvideComponent.
This commit is contained in:
parent
b24b8a507f
commit
a884d98e99
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue