MSI: Send progress and action messages
Mike McCormack
mike at codeweavers.com
Sat Jul 3 20:19:51 CDT 2004
ChangeLog:
<aric at codeweavers.com>
* Send progress and action messages
-------------- next part --------------
diff -ur dlls/msi.old/action.c dlls/msi/action.c
--- dlls/msi.old/action.c 2004-07-03 20:16:36.000000000 -0500
+++ dlls/msi/action.c 2004-07-03 20:16:47.000000000 -0500
@@ -167,6 +167,26 @@
static const WCHAR cszrsb[]={']',0};
static const WCHAR cszbs[]={'\\',0};
+const static WCHAR szCreateFolders[] =
+ {'C','r','e','a','t','e','F','o','l','d','e','r','s',0};
+const static WCHAR szCostFinalize[] =
+ {'C','o','s','t','F','i','n','a','l','i','z','e',0};
+const static WCHAR szInstallFiles[] =
+ {'I','n','s','t','a','l','l','F','i','l','e','s',0};
+const static WCHAR szDuplicateFiles[] =
+ {'D','u','p','l','i','c','a','t','e','F','i','l','e','s',0};
+const static WCHAR szWriteRegistryValues[] =
+{'W','r','i','t','e','R','e','g','i','s','t','r','y','V','a','l','u','e','s',0};
+const static WCHAR szCostInitialize[] =
+ {'C','o','s','t','I','n','i','t','i','a','l','i','z','e',0};
+const static WCHAR szFileCost[] = {'F','i','l','e','C','o','s','t',0};
+const static WCHAR szInstallInitialize[] =
+ {'I','n','s','t','a','l','l','I','n','i','t','i','a','l','i','z','e',0};
+const static WCHAR szInstallValidate[] =
+ {'I','n','s','t','a','l','l','V','a','l','i','d','a','t','e',0};
+const static WCHAR szLaunchConditions[] =
+ {'L','a','u','n','c','h','C','o','n','d','i','t','i','o','n','s',0};
+
/********************************************************
* helper functions to get around current HACKS and such
@@ -275,7 +295,7 @@
}
}
-static void progress_message(MSIHANDLE hPackage, int a, int b, int c, int d )
+static void ui_progress(MSIHANDLE hPackage, int a, int b, int c, int d )
{
MSIHANDLE row;
@@ -288,6 +308,176 @@
MsiCloseHandle(row);
}
+static void ui_actiondata(MSIHANDLE hPackage, LPCWSTR action, MSIHANDLE record)
+{
+ 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};
+ WCHAR message[1024];
+ UINT rc;
+ MSIHANDLE view;
+ MSIHANDLE row = 0;
+ WCHAR *ActionFormat=NULL;
+ DWORD sz;
+ WCHAR Query[1024];
+ MSIHANDLE db;
+ LPWSTR ptr;
+
+ sprintfW(Query,Query_t,action);
+ db = MsiGetActiveDatabase(hPackage);
+ rc = MsiDatabaseOpenViewW(db, Query, &view);
+ MsiCloseHandle(db);
+ MsiViewExecute(view, 0);
+ rc = MsiViewFetch(view,&row);
+ if (rc != ERROR_SUCCESS)
+ {
+ MsiViewClose(view);
+ MsiCloseHandle(view);
+ return;
+ }
+
+ if (MsiRecordIsNull(row,3))
+ {
+ MsiCloseHandle(row);
+ MsiViewClose(view);
+ MsiCloseHandle(view);
+ return;
+ }
+ sz = 0;
+ MsiRecordGetStringW(row,3,NULL,&sz);
+ sz++;
+ ActionFormat = HeapAlloc(GetProcessHeap(),0,sz*sizeof(WCHAR));
+ MsiRecordGetStringW(row,3,ActionFormat,&sz);
+ MsiCloseHandle(row);
+ MsiViewClose(view);
+ MsiCloseHandle(view);
+
+ message[0]=0;
+ ptr = ActionFormat;
+ while (*ptr)
+ {
+ LPWSTR ptr2;
+ LPWSTR data=NULL;
+ WCHAR tmp[1023];
+ INT field;
+
+ ptr2 = strchrW(ptr,'[');
+ if (ptr2)
+ {
+ strncpyW(tmp,ptr,ptr2-ptr);
+ tmp[ptr2-ptr]=0;
+ strcatW(message,tmp);
+ ptr2++;
+ field = atoiW(ptr2);
+ sz = 0;
+ MsiRecordGetStringW(record,field,NULL,&sz);
+ sz++;
+ data = HeapAlloc(GetProcessHeap(),0,sz*sizeof(WCHAR));
+ MsiRecordGetStringW(record,field,data,&sz);
+ strcatW(message,data);
+ HeapFree(GetProcessHeap(),0,data);
+ ptr=strchrW(ptr2,']');
+ ptr++;
+ }
+ else
+ {
+ strcatW(message,ptr);
+ break;
+ }
+ }
+
+ row = MsiCreateRecord(1);
+ MsiRecordSetStringW(row,1,message);
+
+ MsiProcessMessage(hPackage, INSTALLMESSAGE_ACTIONDATA, row);
+ MsiCloseHandle(row);
+ HeapFree(GetProcessHeap(),0,ActionFormat);
+}
+
+
+static void ui_actionstart(MSIHANDLE hPackage, LPCWSTR action)
+{
+ static const WCHAR template_s[]=
+{'A','c','t','i','o','n',' ','%','s',':',' ','%','s','.',' ','%','s','.',0};
+ static const WCHAR format[] =
+{'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0};
+ 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};
+ WCHAR message[1024];
+ WCHAR timet[0x100];
+ UINT rc;
+ MSIHANDLE view;
+ MSIHANDLE row = 0;
+ WCHAR *ActionText=NULL;
+ DWORD sz;
+ WCHAR Query[1024];
+ MSIHANDLE db;
+
+ GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, format, timet, 0x100);
+
+ sprintfW(Query,Query_t,action);
+ db = MsiGetActiveDatabase(hPackage);
+ rc = MsiDatabaseOpenViewW(db, Query, &view);
+ MsiCloseHandle(db);
+ MsiViewExecute(view, 0);
+ rc = MsiViewFetch(view,&row);
+ if (rc != ERROR_SUCCESS)
+ {
+ MsiViewClose(view);
+ MsiCloseHandle(view);
+ return;
+ }
+
+ sz = 0;
+ MsiRecordGetStringW(row,2,NULL,&sz);
+ sz++;
+ ActionText = HeapAlloc(GetProcessHeap(),0,sz*sizeof(WCHAR));
+ MsiRecordGetStringW(row,2,ActionText,&sz);
+ MsiCloseHandle(row);
+ MsiViewClose(view);
+ MsiCloseHandle(view);
+
+ sprintfW(message,template_s,timet,action,ActionText);
+
+ row = MsiCreateRecord(1);
+ MsiRecordSetStringW(row,1,message);
+
+ MsiProcessMessage(hPackage, INSTALLMESSAGE_ACTIONSTART, row);
+ MsiCloseHandle(row);
+ HeapFree(GetProcessHeap(),0,ActionText);
+}
+
+static void ui_actioninfo(MSIHANDLE hPackage, LPCWSTR action, BOOL start,
+ UINT rc)
+{
+ MSIHANDLE 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 = MsiCreateRecord(1);
+ MsiRecordSetStringW(row,1,message);
+
+ MsiProcessMessage(hPackage, INSTALLMESSAGE_INFO, row);
+ MsiCloseHandle(row);
+}
+
/****************************************************
* TOP level entry points
*****************************************************/
@@ -596,53 +786,36 @@
*/
UINT ACTION_PerformAction(MSIHANDLE hPackage, const WCHAR *action)
{
- const static WCHAR szCreateFolders[] =
- {'C','r','e','a','t','e','F','o','l','d','e','r','s',0};
- const static WCHAR szCostFinalize[] =
- {'C','o','s','t','F','i','n','a','l','i','z','e',0};
- const static WCHAR szInstallFiles[] =
- {'I','n','s','t','a','l','l','F','i','l','e','s',0};
- const static WCHAR szDuplicateFiles[] =
- {'D','u','p','l','i','c','a','t','e','F','i','l','e','s',0};
- const static WCHAR szWriteRegistryValues[] =
-{'W','r','i','t','e','R','e','g','i','s','t','r','y','V','a','l','u','e','s',0};
- const static WCHAR szCostInitialize[] =
- {'C','o','s','t','I','n','i','t','i','a','l','i','z','e',0};
- const static WCHAR szFileCost[] =
- {'F','i','l','e','C','o','s','t',0};
- const static WCHAR szInstallInitialize[] =
-{'I','n','s','t','a','l','l','I','n','i','t','i','a','l','i','z','e',0};
- const static WCHAR szInstallValidate[] =
-{'I','n','s','t','a','l','l','V','a','l','i','d','a','t','e',0};
- const static WCHAR szLaunchConditions[] =
-{'L','a','u','n','c','h','C','o','n','d','i','t','i','o','n','s',0};
+ UINT rc = ERROR_SUCCESS;
TRACE("Performing action (%s)\n",debugstr_w(action));
- progress_message(hPackage,2,25,0,0);
+ ui_actioninfo(hPackage, action, TRUE, 0);
+ ui_actionstart(hPackage, action);
+ ui_progress(hPackage,2,1,0,0);
/* pre install, setup and configureation block */
if (strcmpW(action,szLaunchConditions)==0)
- return ACTION_LaunchConditions(hPackage);
- if (strcmpW(action,szCostInitialize)==0)
- return ACTION_CostInitialize(hPackage);
- if (strcmpW(action,szFileCost)==0)
- return ACTION_FileCost(hPackage);
- if (strcmpW(action,szCostFinalize)==0)
- return ACTION_CostFinalize(hPackage);
- if (strcmpW(action,szInstallValidate)==0)
- return ACTION_InstallValidate(hPackage);
+ rc = ACTION_LaunchConditions(hPackage);
+ else if (strcmpW(action,szCostInitialize)==0)
+ rc = ACTION_CostInitialize(hPackage);
+ else if (strcmpW(action,szFileCost)==0)
+ rc = ACTION_FileCost(hPackage);
+ else if (strcmpW(action,szCostFinalize)==0)
+ rc = ACTION_CostFinalize(hPackage);
+ else if (strcmpW(action,szInstallValidate)==0)
+ rc = ACTION_InstallValidate(hPackage);
/* install block */
- if (strcmpW(action,szInstallInitialize)==0)
- return ACTION_InstallInitialize(hPackage);
- if (strcmpW(action,szCreateFolders)==0)
- return ACTION_CreateFolders(hPackage);
- if (strcmpW(action,szInstallFiles)==0)
- return ACTION_InstallFiles(hPackage);
- if (strcmpW(action,szDuplicateFiles)==0)
- return ACTION_DuplicateFiles(hPackage);
- if (strcmpW(action,szWriteRegistryValues)==0)
- return ACTION_WriteRegistryValues(hPackage);
+ else if (strcmpW(action,szInstallInitialize)==0)
+ rc = ACTION_InstallInitialize(hPackage);
+ else if (strcmpW(action,szCreateFolders)==0)
+ rc = ACTION_CreateFolders(hPackage);
+ else if (strcmpW(action,szInstallFiles)==0)
+ rc = ACTION_InstallFiles(hPackage);
+ else if (strcmpW(action,szDuplicateFiles)==0)
+ rc = ACTION_DuplicateFiles(hPackage);
+ else if (strcmpW(action,szWriteRegistryValues)==0)
+ rc = ACTION_WriteRegistryValues(hPackage);
/*
Current called during itunes but unimplemented
@@ -704,16 +877,20 @@
InstallFinalize
.
*/
- if (ACTION_CustomAction(hPackage,action) != ERROR_SUCCESS)
+ else if ((rc = ACTION_CustomAction(hPackage,action)) != ERROR_SUCCESS)
+ {
FIXME("UNHANDLED MSI ACTION %s\n",debugstr_w(action));
+ rc = ERROR_SUCCESS;
+ }
- return ERROR_SUCCESS;
+ ui_actioninfo(hPackage, action, FALSE, rc);
+ return rc;
}
static UINT ACTION_CustomAction(MSIHANDLE hPackage,const WCHAR *action)
{
- UINT rc;
+ UINT rc = ERROR_SUCCESS;
MSIHANDLE view;
MSIHANDLE row = 0;
WCHAR ExecSeqQuery[1024] =
@@ -776,7 +953,7 @@
case 35: /* Directory set with formatted text. */
case 51: /* Property set with formatted text. */
deformat_string(hPackage,target,&deformated);
- MsiSetPropertyW(hPackage,source,deformated);
+ rc = MsiSetPropertyW(hPackage,source,deformated);
HeapFree(GetProcessHeap(),0,deformated);
break;
default:
@@ -1055,6 +1232,7 @@
WCHAR full_path[MAX_PATH];
DWORD sz;
MSIHANDLE row = 0;
+ MSIHANDLE uirow;
rc = MsiViewFetch(view,&row);
if (rc != ERROR_SUCCESS)
@@ -1085,6 +1263,12 @@
TRACE("Folder is %s\n",debugstr_w(full_path));
+ /* UI stuff */
+ uirow = MsiCreateRecord(1);
+ MsiRecordSetStringW(uirow,1,full_path);
+ ui_actiondata(hPackage,szCreateFolders,uirow);
+ MsiCloseHandle(uirow);
+
if (folder->State == 0)
create_full_pathW(full_path);
@@ -2129,12 +2313,17 @@
UINT rc = ERROR_SUCCESS;
INT index;
MSIPACKAGE *package;
+ MSIHANDLE uirow;
+ WCHAR uipath[MAX_PATH];
package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
if (!package)
return ERROR_INVALID_HANDLE;
+ /* increment progress bar each time action data is sent */
+ ui_progress(hPackage,1,1,1,0);
+
for (index = 0; index < package->loaded_files; index++)
{
WCHAR path_to_source[MAX_PATH];
@@ -2178,8 +2367,19 @@
TRACE("file paths %s to %s\n",debugstr_w(file->SourcePath),
debugstr_w(file->TargetPath));
- progress_message(hPackage,2,1,0,0);
+ /* the UI chunk */
+ uirow=MsiCreateRecord(9);
+ MsiRecordSetStringW(uirow,1,file->File);
+ strcpyW(uipath,file->TargetPath);
+ *(strrchrW(uipath,'\\')+1)=0;
+ MsiRecordSetStringW(uirow,9,uipath);
+ MsiRecordSetInteger(uirow,6,file->FileSize);
+ ui_actiondata(hPackage,szInstallFiles,uirow);
+ MsiCloseHandle(uirow);
+
rc = !MoveFileW(file->SourcePath,file->TargetPath);
+ ui_progress(hPackage,2,0,0,0);
+
if (rc)
ERR("Unable to move file\n");
else
@@ -2453,8 +2653,21 @@
return rc;
}
+ /* increment progress bar each time action data is sent */
+ ui_progress(hPackage,1,1,1,0);
+
while (1)
{
+ static const WCHAR szHCR[] =
+{'H','K','E','Y','_','C','L','A','S','S','E','S','_','R','O','O','T','\\',0};
+ static const WCHAR szHCU[] =
+{'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R','\\',0};
+ static const WCHAR szHLM[] =
+{'H','K','E','Y','_','L','O','C','A','L','_','M','A','C','H','I','N','E',
+'\\',0};
+ static const WCHAR szHU[] =
+{'H','K','E','Y','_','U','S','E','R','S','\\',0};
+
WCHAR key[0x100];
WCHAR name[0x100];
LPWSTR value;
@@ -2463,6 +2676,8 @@
DWORD type,size;
WCHAR component[0x100];
INT component_index;
+ MSIHANDLE uirow;
+ WCHAR uikey[0x110];
INT root;
DWORD sz=0x100;
@@ -2504,14 +2719,17 @@
else
MsiRecordGetStringW(row,4,name,&sz);
-
/* get the root key */
switch (root)
{
- case 0: root_key = HKEY_CLASSES_ROOT; break;
- case 1: root_key = HKEY_CURRENT_USER; break;
- case 2: root_key = HKEY_LOCAL_MACHINE; break;
- case 3: root_key = HKEY_USERS; break;
+ case 0: root_key = HKEY_CLASSES_ROOT;
+ strcpyW(uikey,szHCR); break;
+ case 1: root_key = HKEY_CURRENT_USER;
+ strcpyW(uikey,szHCU); break;
+ case 2: root_key = HKEY_LOCAL_MACHINE;
+ strcpyW(uikey,szHLM); break;
+ case 3: root_key = HKEY_USERS;
+ strcpyW(uikey,szHU); break;
default:
ERR("Unknown root %i\n",root);
root_key=NULL;
@@ -2523,6 +2741,7 @@
continue;
}
+ strcatW(uikey,key);
if (RegCreateKeyW( root_key, key, &hkey))
{
ERR("Could not create key %s\n",debugstr_w(key));
@@ -2536,15 +2755,28 @@
value = HeapAlloc(GetProcessHeap(),0,sz * sizeof(WCHAR));
MsiRecordGetStringW(row,5,value,&sz);
value_data = parse_value(hPackage, value, &type, &size);
- HeapFree(GetProcessHeap(),0,value);
if (value_data)
{
TRACE("Setting value %s\n",debugstr_w(name));
RegSetValueExW(hkey, name, 0, type, value_data, size);
+
+ uirow = MsiCreateRecord(3);
+ MsiRecordSetStringW(uirow,2,name);
+ MsiRecordSetStringW(uirow,1,uikey);
+
+ if (type == REG_SZ)
+ MsiRecordSetStringW(uirow,3,(LPWSTR)value_data);
+ else
+ MsiRecordSetStringW(uirow,3,value);
+
+ ui_actiondata(hPackage,szWriteRegistryValues,uirow);
+ ui_progress(hPackage,2,0,0,0);
+ MsiCloseHandle(uirow);
+
HeapFree(GetProcessHeap(),0,value_data);
}
- progress_message(hPackage,2,1,0,0);
+ HeapFree(GetProcessHeap(),0,value);
MsiCloseHandle(row);
}
@@ -2705,45 +2937,15 @@
{
DWORD progress = 0;
static const CHAR q1[]="SELECT * FROM Registry";
- static const CHAR q2[]=
-"select Action from InstallExecuteSequence where Sequence > 0 order by Sequence";
UINT rc;
MSIHANDLE view;
MSIHANDLE row = 0;
MSIHANDLE db;
- BOOL flipit= FALSE;
MSIPACKAGE* package;
TRACE(" InstallValidate \n");
db = MsiGetActiveDatabase(hPackage);
- rc = MsiDatabaseOpenViewA(db, q2, &view);
- rc = MsiViewExecute(view, 0);
-
- while (1)
- {
- rc = MsiViewFetch(view,&row);
- if (rc != ERROR_SUCCESS)
- {
- rc = ERROR_SUCCESS;
- break;
- }
- if (!flipit)
- {
- CHAR buf[0x100];
- DWORD sz=0x100;
- MsiRecordGetStringA(row,1,buf,&sz);
- if (strcmp(buf,"InstallValidate")==0)
- flipit=TRUE;
- }
- else
- progress +=25;
-
- MsiCloseHandle(row);
- }
- MsiViewClose(view);
- MsiCloseHandle(view);
-
rc = MsiDatabaseOpenViewA(db, q1, &view);
rc = MsiViewExecute(view, 0);
while (1)
@@ -2763,7 +2965,7 @@
MsiCloseHandle(db);
package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
- progress_message(hPackage,0,progress+package->loaded_files,0,0);
+ ui_progress(hPackage,0,progress+package->loaded_files,0,0);
return ERROR_SUCCESS;
}
diff -ur dlls/msi.old/package.c dlls/msi/package.c
--- dlls/msi.old/package.c 2004-07-03 20:16:36.000000000 -0500
+++ dlls/msi/package.c 2004-07-03 20:16:47.000000000 -0500
@@ -419,10 +419,13 @@
if (msg_field > 1)
{
- sprintf(number," %i: ",i);
+ sprintf(number,"%i: ",i);
strcat(message,number);
}
strcat(message,tmp);
+ if (msg_field > 1)
+ strcat(message," ");
+
HeapFree(GetProcessHeap(),0,tmp);
}
More information about the wine-patches
mailing list