📄 action.c
字号:
/*
* Implementation of the Microsoft Installer (msi.dll)
*
* Copyright 2004,2005 Aric Stewart for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
/*
* Pages I need
*
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/installexecutesequence_table.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/standard_actions_reference.asp
*/
#include <stdarg.h>
#define COBJMACROS
#include "stdio.h"
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "winreg.h"
#include "winsvc.h"
#include "wine/debug.h"
#include "msidefs.h"
#include "msipriv.h"
#include "winuser.h"
#include "shlobj.h"
#include "wine/unicode.h"
#include "winver.h"
#define REG_PROGRESS_VALUE 13200
#define COMPONENT_PROGRESS_VALUE 24000
WINE_DEFAULT_DEBUG_CHANNEL(msi);
/*
* Prototypes
*/
static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran);
static UINT ACTION_ProcessUISequence(MSIPACKAGE *package);
static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq, BOOL UI);
/*
* consts and values used
*/
static const WCHAR c_colon[] = {'C',':','\\',0};
static const WCHAR szCreateFolders[] =
{'C','r','e','a','t','e','F','o','l','d','e','r','s',0};
static const WCHAR szCostFinalize[] =
{'C','o','s','t','F','i','n','a','l','i','z','e',0};
const WCHAR szInstallFiles[] =
{'I','n','s','t','a','l','l','F','i','l','e','s',0};
const WCHAR szDuplicateFiles[] =
{'D','u','p','l','i','c','a','t','e','F','i','l','e','s',0};
static const WCHAR szWriteRegistryValues[] =
{'W','r','i','t','e','R','e','g','i','s','t','r','y',
'V','a','l','u','e','s',0};
static const WCHAR szCostInitialize[] =
{'C','o','s','t','I','n','i','t','i','a','l','i','z','e',0};
static const WCHAR szFileCost[] =
{'F','i','l','e','C','o','s','t',0};
static const WCHAR szInstallInitialize[] =
{'I','n','s','t','a','l','l','I','n','i','t','i','a','l','i','z','e',0};
static const WCHAR szInstallValidate[] =
{'I','n','s','t','a','l','l','V','a','l','i','d','a','t','e',0};
static const WCHAR szLaunchConditions[] =
{'L','a','u','n','c','h','C','o','n','d','i','t','i','o','n','s',0};
static const WCHAR szProcessComponents[] =
{'P','r','o','c','e','s','s','C','o','m','p','o','n','e','n','t','s',0};
static const WCHAR szRegisterTypeLibraries[] =
{'R','e','g','i','s','t','e','r','T','y','p','e',
'L','i','b','r','a','r','i','e','s',0};
const WCHAR szRegisterClassInfo[] =
{'R','e','g','i','s','t','e','r','C','l','a','s','s','I','n','f','o',0};
const WCHAR szRegisterProgIdInfo[] =
{'R','e','g','i','s','t','e','r','P','r','o','g','I','d','I','n','f','o',0};
static const WCHAR szCreateShortcuts[] =
{'C','r','e','a','t','e','S','h','o','r','t','c','u','t','s',0};
static const WCHAR szPublishProduct[] =
{'P','u','b','l','i','s','h','P','r','o','d','u','c','t',0};
static const WCHAR szWriteIniValues[] =
{'W','r','i','t','e','I','n','i','V','a','l','u','e','s',0};
static const WCHAR szSelfRegModules[] =
{'S','e','l','f','R','e','g','M','o','d','u','l','e','s',0};
static const WCHAR szPublishFeatures[] =
{'P','u','b','l','i','s','h','F','e','a','t','u','r','e','s',0};
static const WCHAR szRegisterProduct[] =
{'R','e','g','i','s','t','e','r','P','r','o','d','u','c','t',0};
static const WCHAR szInstallExecute[] =
{'I','n','s','t','a','l','l','E','x','e','c','u','t','e',0};
static const WCHAR szInstallExecuteAgain[] =
{'I','n','s','t','a','l','l','E','x','e','c','u','t','e',
'A','g','a','i','n',0};
static const WCHAR szInstallFinalize[] =
{'I','n','s','t','a','l','l','F','i','n','a','l','i','z','e',0};
static const WCHAR szForceReboot[] =
{'F','o','r','c','e','R','e','b','o','o','t',0};
static const WCHAR szResolveSource[] =
{'R','e','s','o','l','v','e','S','o','u','r','c','e',0};
static const WCHAR szAppSearch[] =
{'A','p','p','S','e','a','r','c','h',0};
static const WCHAR szAllocateRegistrySpace[] =
{'A','l','l','o','c','a','t','e','R','e','g','i','s','t','r','y',
'S','p','a','c','e',0};
static const WCHAR szBindImage[] =
{'B','i','n','d','I','m','a','g','e',0};
static const WCHAR szCCPSearch[] =
{'C','C','P','S','e','a','r','c','h',0};
static const WCHAR szDeleteServices[] =
{'D','e','l','e','t','e','S','e','r','v','i','c','e','s',0};
static const WCHAR szDisableRollback[] =
{'D','i','s','a','b','l','e','R','o','l','l','b','a','c','k',0};
static const WCHAR szExecuteAction[] =
{'E','x','e','c','u','t','e','A','c','t','i','o','n',0};
const WCHAR szFindRelatedProducts[] =
{'F','i','n','d','R','e','l','a','t','e','d',
'P','r','o','d','u','c','t','s',0};
static const WCHAR szInstallAdminPackage[] =
{'I','n','s','t','a','l','l','A','d','m','i','n',
'P','a','c','k','a','g','e',0};
static const WCHAR szInstallSFPCatalogFile[] =
{'I','n','s','t','a','l','l','S','F','P','C','a','t','a','l','o','g',
'F','i','l','e',0};
static const WCHAR szIsolateComponents[] =
{'I','s','o','l','a','t','e','C','o','m','p','o','n','e','n','t','s',0};
const WCHAR szMigrateFeatureStates[] =
{'M','i','g','r','a','t','e','F','e','a','t','u','r','e',
'S','t','a','t','e','s',0};
const WCHAR szMoveFiles[] =
{'M','o','v','e','F','i','l','e','s',0};
static const WCHAR szMsiPublishAssemblies[] =
{'M','s','i','P','u','b','l','i','s','h',
'A','s','s','e','m','b','l','i','e','s',0};
static const WCHAR szMsiUnpublishAssemblies[] =
{'M','s','i','U','n','p','u','b','l','i','s','h',
'A','s','s','e','m','b','l','i','e','s',0};
static const WCHAR szInstallODBC[] =
{'I','n','s','t','a','l','l','O','D','B','C',0};
static const WCHAR szInstallServices[] =
{'I','n','s','t','a','l','l','S','e','r','v','i','c','e','s',0};
const WCHAR szPatchFiles[] =
{'P','a','t','c','h','F','i','l','e','s',0};
static const WCHAR szPublishComponents[] =
{'P','u','b','l','i','s','h','C','o','m','p','o','n','e','n','t','s',0};
static const WCHAR szRegisterComPlus[] =
{'R','e','g','i','s','t','e','r','C','o','m','P','l','u','s',0};
const WCHAR szRegisterExtensionInfo[] =
{'R','e','g','i','s','t','e','r','E','x','t','e','n','s','i','o','n',
'I','n','f','o',0};
static const WCHAR szRegisterFonts[] =
{'R','e','g','i','s','t','e','r','F','o','n','t','s',0};
const WCHAR szRegisterMIMEInfo[] =
{'R','e','g','i','s','t','e','r','M','I','M','E','I','n','f','o',0};
static const WCHAR szRegisterUser[] =
{'R','e','g','i','s','t','e','r','U','s','e','r',0};
const WCHAR szRemoveDuplicateFiles[] =
{'R','e','m','o','v','e','D','u','p','l','i','c','a','t','e',
'F','i','l','e','s',0};
static const WCHAR szRemoveEnvironmentStrings[] =
{'R','e','m','o','v','e','E','n','v','i','r','o','n','m','e','n','t',
'S','t','r','i','n','g','s',0};
const WCHAR szRemoveExistingProducts[] =
{'R','e','m','o','v','e','E','x','i','s','t','i','n','g',
'P','r','o','d','u','c','t','s',0};
const WCHAR szRemoveFiles[] =
{'R','e','m','o','v','e','F','i','l','e','s',0};
static const WCHAR szRemoveFolders[] =
{'R','e','m','o','v','e','F','o','l','d','e','r','s',0};
static const WCHAR szRemoveIniValues[] =
{'R','e','m','o','v','e','I','n','i','V','a','l','u','e','s',0};
static const WCHAR szRemoveODBC[] =
{'R','e','m','o','v','e','O','D','B','C',0};
static const WCHAR szRemoveRegistryValues[] =
{'R','e','m','o','v','e','R','e','g','i','s','t','r','y',
'V','a','l','u','e','s',0};
static const WCHAR szRemoveShortcuts[] =
{'R','e','m','o','v','e','S','h','o','r','t','c','u','t','s',0};
static const WCHAR szRMCCPSearch[] =
{'R','M','C','C','P','S','e','a','r','c','h',0};
static const WCHAR szScheduleReboot[] =
{'S','c','h','e','d','u','l','e','R','e','b','o','o','t',0};
static const WCHAR szSelfUnregModules[] =
{'S','e','l','f','U','n','r','e','g','M','o','d','u','l','e','s',0};
static const WCHAR szSetODBCFolders[] =
{'S','e','t','O','D','B','C','F','o','l','d','e','r','s',0};
static const WCHAR szStartServices[] =
{'S','t','a','r','t','S','e','r','v','i','c','e','s',0};
static const WCHAR szStopServices[] =
{'S','t','o','p','S','e','r','v','i','c','e','s',0};
static const WCHAR szUnpublishComponents[] =
{'U','n','p','u','b','l','i','s','h',
'C','o','m','p','o','n','e','n','t','s',0};
static const WCHAR szUnpublishFeatures[] =
{'U','n','p','u','b','l','i','s','h','F','e','a','t','u','r','e','s',0};
const WCHAR szUnregisterClassInfo[] =
{'U','n','r','e','g','i','s','t','e','r','C','l','a','s','s',
'I','n','f','o',0};
static const WCHAR szUnregisterComPlus[] =
{'U','n','r','e','g','i','s','t','e','r','C','o','m','P','l','u','s',0};
const WCHAR szUnregisterExtensionInfo[] =
{'U','n','r','e','g','i','s','t','e','r',
'E','x','t','e','n','s','i','o','n','I','n','f','o',0};
static const WCHAR szUnregisterFonts[] =
{'U','n','r','e','g','i','s','t','e','r','F','o','n','t','s',0};
const WCHAR szUnregisterMIMEInfo[] =
{'U','n','r','e','g','i','s','t','e','r','M','I','M','E','I','n','f','o',0};
const WCHAR szUnregisterProgIdInfo[] =
{'U','n','r','e','g','i','s','t','e','r','P','r','o','g','I','d',
'I','n','f','o',0};
static const WCHAR szUnregisterTypeLibraries[] =
{'U','n','r','e','g','i','s','t','e','r','T','y','p','e',
'L','i','b','r','a','r','i','e','s',0};
static const WCHAR szValidateProductID[] =
{'V','a','l','i','d','a','t','e','P','r','o','d','u','c','t','I','D',0};
static const WCHAR szWriteEnvironmentStrings[] =
{'W','r','i','t','e','E','n','v','i','r','o','n','m','e','n','t',
'S','t','r','i','n','g','s',0};
/* action handlers */
typedef UINT (*STANDARDACTIONHANDLER)(MSIPACKAGE*);
struct _actions {
LPCWSTR action;
STANDARDACTIONHANDLER handler;
};
static struct _actions StandardActions[];
/********************************************************
* helper functions
********************************************************/
static void ui_actionstart(MSIPACKAGE *package, LPCWSTR action)
{
static const WCHAR Query_t[] =
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
'`','A','c','t','i','o', 'n','T','e','x','t','`',' ',
'W','H','E','R','E', ' ','`','A','c','t','i','o','n','`',' ','=',
' ','\'','%','s','\'',0};
MSIRECORD * row;
row = MSI_QueryGetRecord( package->db, Query_t, action );
if (!row)
return;
MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONSTART, row);
msiobj_release(&row->hdr);
}
static void ui_actioninfo(MSIPACKAGE *package, LPCWSTR action, BOOL start,
UINT rc)
{
MSIRECORD * row;
static const WCHAR template_s[]=
{'A','c','t','i','o','n',' ','s','t','a','r','t',' ','%','s',':',' ',
'%','s', '.',0};
static const WCHAR template_e[]=
{'A','c','t','i','o','n',' ','e','n','d','e','d',' ','%','s',':',' ',
'%','s', '.',' ','R','e','t','u','r','n',' ','v','a','l','u','e',' ',
'%','i','.',0};
static const WCHAR format[] =
{'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0};
WCHAR message[1024];
WCHAR timet[0x100];
GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, format, timet, 0x100);
if (start)
sprintfW(message,template_s,timet,action);
else
sprintfW(message,template_e,timet,action,rc);
row = MSI_CreateRecord(1);
MSI_RecordSetStringW(row,1,message);
MSI_ProcessMessage(package, INSTALLMESSAGE_INFO, row);
msiobj_release(&row->hdr);
}
static UINT msi_parse_command_line( MSIPACKAGE *package, LPCWSTR szCommandLine )
{
LPCWSTR ptr,ptr2;
BOOL quote;
DWORD len;
LPWSTR prop = NULL, val = NULL;
if (!szCommandLine)
return ERROR_SUCCESS;
ptr = szCommandLine;
while (*ptr)
{
if (*ptr==' ')
{
ptr++;
continue;
}
TRACE("Looking at %s\n",debugstr_w(ptr));
ptr2 = strchrW(ptr,'=');
if (!ptr2)
{
ERR("command line contains unknown string : %s\n", debugstr_w(ptr));
break;
}
quote = FALSE;
len = ptr2-ptr;
prop = msi_alloc((len+1)*sizeof(WCHAR));
memcpy(prop,ptr,len*sizeof(WCHAR));
prop[len]=0;
ptr2++;
len = 0;
ptr = ptr2;
while (*ptr && (quote || (!quote && *ptr!=' ')))
{
if (*ptr == '"')
quote = !quote;
ptr++;
len++;
}
if (*ptr2=='"')
{
ptr2++;
len -= 2;
}
val = msi_alloc((len+1)*sizeof(WCHAR));
memcpy(val,ptr2,len*sizeof(WCHAR));
val[len] = 0;
if (lstrlenW(prop) > 0)
{
TRACE("Found commandline property (%s) = (%s)\n",
debugstr_w(prop), debugstr_w(val));
MSI_SetPropertyW(package,prop,val);
}
msi_free(val);
msi_free(prop);
}
return ERROR_SUCCESS;
}
static LPWSTR* msi_split_string( LPCWSTR str, WCHAR sep )
{
LPCWSTR pc;
LPWSTR p, *ret = NULL;
UINT count = 0;
if (!str)
return ret;
/* count the number of substrings */
for ( pc = str, count = 0; pc; count++ )
{
pc = strchrW( pc, sep );
if (pc)
pc++;
}
/* allocate space for an array of substring pointers and the substrings */
ret = msi_alloc( (count+1) * sizeof (LPWSTR) +
(lstrlenW(str)+1) * sizeof(WCHAR) );
if (!ret)
return ret;
/* copy the string and set the pointers */
p = (LPWSTR) &ret[count+1];
lstrcpyW( p, str );
for( count = 0; (ret[count] = p); count++ )
{
p = strchrW( p, sep );
if (p)
*p++ = 0;
}
return ret;
}
static UINT msi_check_transform_applicable( MSIPACKAGE *package, IStorage *patch )
{
WCHAR szProductCode[] = { 'P','r','o','d','u','c','t','C','o','d','e',0 };
LPWSTR prod_code, patch_product;
UINT ret;
prod_code = msi_dup_property( package, szProductCode );
patch_product = msi_get_suminfo_product( patch );
TRACE("db = %s patch = %s\n", debugstr_w(prod_code), debugstr_w(patch_product));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -