@@ -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+
968985static 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+
10121098static 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
14581546end :
0 commit comments