Skip to content

Commit 373ffef

Browse files
winesynclearn-more
authored andcommitted
[WINESYNC] msi: Add support for custom action type 7.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=44618 Signed-off-by: Hans Leidekker <[email protected]> Signed-off-by: Alexandre Julliard <[email protected]> wine commit id 54ef6e5e3932a5ce747fca717c697b67f2bd3e24 by Hans Leidekker <[email protected]>
1 parent be64b5c commit 373ffef

File tree

1 file changed

+159
-71
lines changed

1 file changed

+159
-71
lines changed

dll/win32/msi/custom.c

Lines changed: 159 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -965,13 +965,28 @@ static UINT HANDLE_CustomType19( MSIPACKAGE *package, const WCHAR *source, const
965965
return ERROR_INSTALL_FAILURE;
966966
}
967967

968+
static WCHAR *build_msiexec_args( const WCHAR *filename, const WCHAR *params )
969+
{
970+
UINT len_filename = lstrlenW( filename ), len_params = lstrlenW( params );
971+
UINT len = ARRAY_SIZE(L"/qb /i ") - 1;
972+
WCHAR *ret;
973+
974+
if (!(ret = msi_alloc( (len + len_filename + len_params + 4) * sizeof(WCHAR) ))) return NULL;
975+
memcpy( ret, L"/qb /i ", sizeof(L"/qb /i ") );
976+
ret[len++] = '"';
977+
memcpy( ret + len, filename, len_filename * sizeof(WCHAR) );
978+
len += len_filename;
979+
ret[len++] = '"';
980+
ret[len++] = ' ';
981+
lstrcpyW( ret + len, params );
982+
return ret;
983+
}
984+
968985
static UINT HANDLE_CustomType23( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
969986
INT type, const WCHAR *action )
970987
{
971-
static const WCHAR msiexecW[] = {'m','s','i','e','x','e','c',0};
972-
static const WCHAR paramsW[] = {'/','q','b',' ','/','i',' '};
973-
WCHAR *dir, *arg, *p;
974-
UINT len_src, len_dir, len_tgt, len = ARRAY_SIZE( paramsW );
988+
WCHAR *dir, *filename, *args, *p;
989+
UINT len_dir, len_source = lstrlenW( source );
975990
HANDLE handle;
976991

977992
if (!(dir = msi_dup_property( package->db, szOriginalDatabase ))) return ERROR_OUTOFMEMORY;
@@ -982,33 +997,104 @@ static UINT HANDLE_CustomType23( MSIPACKAGE *package, const WCHAR *source, const
982997
}
983998
*p = 0;
984999
len_dir = p - dir;
985-
len_src = lstrlenW( source );
986-
len_tgt = lstrlenW( target );
987-
if (!(arg = msi_alloc( (len + len_dir + len_src + len_tgt + 5) * sizeof(WCHAR) )))
1000+
if (!(filename = msi_alloc( (len_dir + len_source + 2) * sizeof(WCHAR) )))
1001+
{
1002+
msi_free( dir );
1003+
return ERROR_OUTOFMEMORY;
1004+
}
1005+
memcpy( filename, dir, len_dir * sizeof(WCHAR) );
1006+
filename[len_dir++] = '\\';
1007+
memcpy( filename + len_dir, source, len_source * sizeof(WCHAR) );
1008+
filename[len_dir + len_source] = 0;
1009+
1010+
if (!(args = build_msiexec_args( filename, target )))
9881011
{
9891012
msi_free( dir );
9901013
return ERROR_OUTOFMEMORY;
9911014
}
992-
memcpy( arg, paramsW, sizeof(paramsW) );
993-
arg[len++] = '"';
994-
memcpy( arg + len, dir, len_dir * sizeof(WCHAR) );
995-
len += len_dir;
996-
arg[len++] = '\\';
997-
memcpy( arg + len, source, len_src * sizeof(WCHAR) );
998-
len += len_src;
999-
arg[len++] = '"';
1000-
arg[len++] = ' ';
1001-
lstrcpyW( arg + len, target );
10021015

10031016
TRACE("installing %s concurrently\n", debugstr_w(source));
10041017

1005-
handle = execute_command( msiexecW, arg, dir );
1018+
handle = execute_command( L"msiexec", args, dir );
10061019
msi_free( dir );
1007-
msi_free( arg );
1020+
msi_free( args );
10081021
if (handle == INVALID_HANDLE_VALUE) return ERROR_SUCCESS;
10091022
return wait_process_handle( package, type, handle, action );
10101023
}
10111024

1025+
static UINT write_substorage_to_file( MSIPACKAGE *package, const WCHAR *source, const WCHAR *filename )
1026+
{
1027+
IStorage *src = NULL, *dst = NULL;
1028+
UINT r = ERROR_FUNCTION_FAILED;
1029+
HRESULT hr;
1030+
1031+
hr = StgCreateDocfile( filename, STGM_CREATE|STGM_TRANSACTED|STGM_WRITE|STGM_SHARE_EXCLUSIVE, 0, &dst );
1032+
if (FAILED( hr ))
1033+
{
1034+
WARN( "can't open destination storage %s (%08x)\n", debugstr_w(filename), hr );
1035+
goto done;
1036+
}
1037+
1038+
hr = IStorage_OpenStorage( package->db->storage, source, NULL, STGM_SHARE_EXCLUSIVE, NULL, 0, &src );
1039+
if (FAILED( hr ))
1040+
{
1041+
WARN( "can't open source storage %s (%08x)\n", debugstr_w(source), hr );
1042+
goto done;
1043+
}
1044+
1045+
hr = IStorage_CopyTo( src, 0, NULL, NULL, dst );
1046+
if (FAILED( hr ))
1047+
{
1048+
ERR( "failed to copy storage %s (%08x)\n", debugstr_w(source), hr );
1049+
goto done;
1050+
}
1051+
1052+
hr = IStorage_Commit( dst, 0 );
1053+
if (FAILED( hr ))
1054+
ERR( "failed to commit storage (%08x)\n", hr );
1055+
else
1056+
r = ERROR_SUCCESS;
1057+
1058+
done:
1059+
if (src) IStorage_Release( src );
1060+
if (dst) IStorage_Release( dst );
1061+
return r;
1062+
}
1063+
1064+
static UINT HANDLE_CustomType7( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
1065+
INT type, const WCHAR *action )
1066+
{
1067+
WCHAR *tmpfile, *args;
1068+
MSIBINARY *binary = NULL;
1069+
HANDLE handle;
1070+
UINT r;
1071+
1072+
if (!(tmpfile = msi_create_temp_file( package->db ))) return ERROR_FUNCTION_FAILED;
1073+
1074+
r = write_substorage_to_file( package, source, tmpfile );
1075+
if (r != ERROR_SUCCESS)
1076+
goto error;
1077+
1078+
if (!(binary = msi_alloc( sizeof(*binary) ))) goto error;
1079+
binary->source = NULL;
1080+
binary->tmpfile = tmpfile;
1081+
list_add_tail( &package->binaries, &binary->entry );
1082+
1083+
if (!(args = build_msiexec_args( tmpfile, target ))) return ERROR_OUTOFMEMORY;
1084+
1085+
TRACE("installing %s concurrently\n", debugstr_w(source));
1086+
1087+
handle = execute_command( L"msiexec", args, L"C:\\" );
1088+
msi_free( args );
1089+
if (handle == INVALID_HANDLE_VALUE) return ERROR_SUCCESS;
1090+
return wait_process_handle( package, type, handle, action );
1091+
1092+
error:
1093+
DeleteFileW( tmpfile );
1094+
msi_free( tmpfile );
1095+
return ERROR_FUNCTION_FAILED;
1096+
}
1097+
10121098
static UINT HANDLE_CustomType50( MSIPACKAGE *package, const WCHAR *source, const WCHAR *target,
10131099
INT type, const WCHAR *action )
10141100
{
@@ -1393,66 +1479,68 @@ UINT ACTION_CustomAction(MSIPACKAGE *package, const WCHAR *action)
13931479

13941480
switch (type & CUSTOM_ACTION_TYPE_MASK)
13951481
{
1396-
case 1: /* DLL file stored in a Binary table stream */
1397-
rc = HANDLE_CustomType1(package,source,target,type,action);
1398-
break;
1399-
case 2: /* EXE file stored in a Binary table stream */
1400-
rc = HANDLE_CustomType2(package,source,target,type,action);
1401-
break;
1402-
case 18: /*EXE file installed with package */
1403-
rc = HANDLE_CustomType18(package,source,target,type,action);
1404-
break;
1405-
case 19: /* Error that halts install */
1406-
rc = HANDLE_CustomType19(package,source,target,type,action);
1407-
break;
1408-
case 17:
1409-
rc = HANDLE_CustomType17(package,source,target,type,action);
1410-
break;
1411-
case 23: /* installs another package in the source tree */
1412-
deformat_string(package,target,&deformated);
1413-
rc = HANDLE_CustomType23(package,source,deformated,type,action);
1414-
msi_free(deformated);
1415-
break;
1416-
case 50: /*EXE file specified by a property value */
1417-
rc = HANDLE_CustomType50(package,source,target,type,action);
1418-
break;
1419-
case 34: /*EXE to be run in specified directory */
1420-
rc = HANDLE_CustomType34(package,source,target,type,action);
1421-
break;
1422-
case 35: /* Directory set with formatted text. */
1423-
deformat_string(package,target,&deformated);
1424-
MSI_SetTargetPathW(package, source, deformated);
1425-
msi_free(deformated);
1426-
break;
1427-
case 51: /* Property set with formatted text. */
1428-
if (!source)
1429-
break;
1430-
1431-
len = deformat_string( package, target, &deformated );
1432-
rc = msi_set_property( package->db, source, deformated, len );
1433-
if (rc == ERROR_SUCCESS && !wcscmp( source, szSourceDir ))
1434-
msi_reset_source_folders( package );
1435-
msi_free(deformated);
1436-
break;
1437-
case 37: /* JScript/VBScript text stored in target column. */
1438-
case 38:
1439-
rc = HANDLE_CustomType37_38(package,source,target,type,action);
1482+
case 1: /* DLL file stored in a Binary table stream */
1483+
rc = HANDLE_CustomType1( package, source, target, type, action );
1484+
break;
1485+
case 2: /* EXE file stored in a Binary table stream */
1486+
rc = HANDLE_CustomType2( package, source, target, type, action );
14401487
break;
14411488
case 5:
1442-
case 6: /* JScript/VBScript file stored in a Binary table stream. */
1443-
rc = HANDLE_CustomType5_6(package,source,target,type,action);
1489+
case 6: /* JScript/VBScript file stored in a Binary table stream */
1490+
rc = HANDLE_CustomType5_6( package, source, target, type, action );
1491+
break;
1492+
case 7: /* Concurrent install from substorage */
1493+
deformat_string( package, target, &deformated );
1494+
rc = HANDLE_CustomType7( package, source, target, type, action );
1495+
msi_free( deformated );
1496+
break;
1497+
case 17:
1498+
rc = HANDLE_CustomType17( package, source, target, type, action );
14441499
break;
1445-
case 21: /* JScript/VBScript file installed with the product. */
1500+
case 18: /* EXE file installed with package */
1501+
rc = HANDLE_CustomType18( package, source, target, type, action );
1502+
break;
1503+
case 19: /* Error that halts install */
1504+
rc = HANDLE_CustomType19( package, source, target, type, action );
1505+
break;
1506+
case 21: /* JScript/VBScript file installed with the product */
14461507
case 22:
1447-
rc = HANDLE_CustomType21_22(package,source,target,type,action);
1508+
rc = HANDLE_CustomType21_22( package, source, target, type, action );
1509+
break;
1510+
case 23: /* Installs another package in the source tree */
1511+
deformat_string( package, target, &deformated );
1512+
rc = HANDLE_CustomType23( package, source, deformated, type, action );
1513+
msi_free( deformated );
1514+
break;
1515+
case 34: /* EXE to be run in specified directory */
1516+
rc = HANDLE_CustomType34( package, source, target, type, action );
1517+
break;
1518+
case 35: /* Directory set with formatted text */
1519+
deformat_string( package, target, &deformated );
1520+
MSI_SetTargetPathW( package, source, deformated );
1521+
msi_free( deformated );
1522+
break;
1523+
case 37: /* JScript/VBScript text stored in target column */
1524+
case 38:
1525+
rc = HANDLE_CustomType37_38( package, source, target, type, action );
1526+
break;
1527+
case 50: /* EXE file specified by a property value */
1528+
rc = HANDLE_CustomType50( package, source, target, type, action );
1529+
break;
1530+
case 51: /* Property set with formatted text */
1531+
if (!source) break;
1532+
len = deformat_string( package, target, &deformated );
1533+
rc = msi_set_property( package->db, source, deformated, len );
1534+
if (rc == ERROR_SUCCESS && !wcscmp( source, szSourceDir )) msi_reset_source_folders( package );
1535+
msi_free( deformated );
14481536
break;
1449-
case 53: /* JScript/VBScript text specified by a property value. */
1537+
case 53: /* JScript/VBScript text specified by a property value */
14501538
case 54:
1451-
rc = HANDLE_CustomType53_54(package,source,target,type,action);
1539+
rc = HANDLE_CustomType53_54( package, source, target, type, action );
14521540
break;
14531541
default:
1454-
FIXME("unhandled action type %u (%s %s)\n", type & CUSTOM_ACTION_TYPE_MASK,
1455-
debugstr_w(source), debugstr_w(target));
1542+
FIXME( "unhandled action type %u (%s %s)\n", type & CUSTOM_ACTION_TYPE_MASK, debugstr_w(source),
1543+
debugstr_w(target) );
14561544
}
14571545

14581546
end:

0 commit comments

Comments
 (0)