--- trunk/reactos/lib/msi/action.c 2005-01-12 09:03:31 UTC (rev 12947)
+++ trunk/reactos/lib/msi/action.c 2005-01-12 09:31:44 UTC (rev 12948)
@@ -51,6 +51,8 @@
#include "ver.h"
#define CUSTOM_ACTION_TYPE_MASK 0x3F
+#define REG_PROGRESS_VALUE 13200
+#define COMPONENT_PROGRESS_VALUE 24000
WINE_DEFAULT_DEBUG_CHANNEL(msi);
@@ -65,8 +67,10 @@
WCHAR Directory[96];
INT Attributes;
- INSTALLSTATE State;
- BOOL Enabled;
+ INSTALLSTATE Installed;
+ INSTALLSTATE ActionRequest;
+ INSTALLSTATE Action;
+
INT ComponentCount;
INT Components[1024]; /* yes hardcoded limit.... I am bad */
INT Cost;
@@ -81,21 +85,23 @@
WCHAR Condition[0x100];
WCHAR KeyPath[96];
- INSTALLSTATE State;
- BOOL FeatureState;
+ INSTALLSTATE Installed;
+ INSTALLSTATE ActionRequest;
+ INSTALLSTATE Action;
+
BOOL Enabled;
INT Cost;
} MSICOMPONENT;
typedef struct tagMSIFOLDER
{
- WCHAR Directory[96];
- WCHAR TargetDefault[96];
- WCHAR SourceDefault[96];
+ LPWSTR Directory;
+ LPWSTR TargetDefault;
+ LPWSTR SourceDefault;
- WCHAR ResolvedTarget[MAX_PATH];
- WCHAR ResolvedSource[MAX_PATH];
- WCHAR Property[MAX_PATH]; /* initially set property */
+ LPWSTR ResolvedTarget;
+ LPWSTR ResolvedSource;
+ LPWSTR Property; /* initially set property */
INT ParentIndex;
INT State;
/* 0 = uninitialized */
@@ -108,12 +114,12 @@
typedef struct tagMSIFILE
{
- WCHAR File[72];
+ LPWSTR File;
INT ComponentIndex;
- WCHAR FileName[MAX_PATH];
+ LPWSTR FileName;
INT FileSize;
- WCHAR Version[72];
- WCHAR Language[20];
+ LPWSTR Version;
+ LPWSTR Language;
INT Attributes;
INT Sequence;
@@ -123,8 +129,8 @@
/* 2 = present but replace */
/* 3 = present do not replace */
/* 4 = Installed */
- WCHAR SourcePath[MAX_PATH];
- WCHAR TargetPath[MAX_PATH];
+ LPWSTR SourcePath;
+ LPWSTR TargetPath;
BOOL Temporary;
}MSIFILE;
@@ -134,6 +140,7 @@
static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran);
static UINT ACTION_ProcessUISequence(MSIPACKAGE *package);
+static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq);
UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action);
static UINT ACTION_LaunchConditions(MSIPACKAGE *package);
@@ -158,15 +165,15 @@
const LPWSTR target, const INT type);
static UINT HANDLE_CustomType2(MSIPACKAGE *package, const LPWSTR source,
const LPWSTR target, const INT type);
-static UINT HANDLE_CustomType18(MSIPACKAGE *package, const LPWSTR source,
+static UINT HANDLE_CustomType18(MSIPACKAGE *package, const LPWSTR source,
const LPWSTR target, const INT type);
-static UINT HANDLE_CustomType50(MSIPACKAGE *package, const LPWSTR source,
+static UINT HANDLE_CustomType50(MSIPACKAGE *package, const LPWSTR source,
const LPWSTR target, const INT type);
-static UINT HANDLE_CustomType34(MSIPACKAGE *package, const LPWSTR source,
+static UINT HANDLE_CustomType34(MSIPACKAGE *package, const LPWSTR source,
const LPWSTR target, const INT type);
static DWORD deformat_string(MSIPACKAGE *package, WCHAR* ptr,WCHAR** data);
-static UINT resolve_folder(MSIPACKAGE *package, LPCWSTR name, LPWSTR path,
+static LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name,
BOOL source, BOOL set_prop, MSIFOLDER **folder);
static int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path);
@@ -223,12 +230,9 @@
********************************************************/
inline static void reduce_to_longfilename(WCHAR* filename)
{
- if (strchrW(filename,'|'))
- {
- WCHAR newname[MAX_PATH];
- strcpyW(newname,strchrW(filename,'|')+1);
- strcpyW(filename,newname);
- }
+ LPWSTR p = strchrW(filename,'|');
+ if (p)
+ memmove(filename, p+1, (strlenW(p+1)+1)*sizeof(WCHAR));
}
inline static char *strdupWtoA( const WCHAR *str )
@@ -256,6 +260,15 @@
return ret;
}
+static LPWSTR dupstrW(LPCWSTR src)
+{
+ LPWSTR dest;
+ if (!src) return NULL;
+ dest = HeapAlloc(GetProcessHeap(), 0, (strlenW(src)+1)*sizeof(WCHAR));
+ strcpyW(dest, src);
+ return dest;
+}
+
inline static WCHAR *load_dynamic_stringW(MSIRECORD *row, INT index)
{
UINT rc;
@@ -263,16 +276,58 @@
LPWSTR ret;
sz = 0;
- rc = MSI_RecordGetStringW(row,index,NULL,&sz);
- if (sz <= 0)
+ if (MSI_RecordIsNull(row,index))
return NULL;
+ rc = MSI_RecordGetStringW(row,index,NULL,&sz);
+
+ /* having an empty string is different than NULL */
+ if (sz == 0)
+ {
+ ret = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR));
+ ret[0] = 0;
+ return ret;
+ }
+
sz ++;
ret = HeapAlloc(GetProcessHeap(),0,sz * sizeof (WCHAR));
rc = MSI_RecordGetStringW(row,index,ret,&sz);
+ if (rc!=ERROR_SUCCESS)
+ {
+ ERR("Unable to load dynamic string\n");
+ HeapFree(GetProcessHeap(), 0, ret);
+ ret = NULL;
+ }
return ret;
}
+inline static LPWSTR load_dynamic_property(MSIPACKAGE *package, LPCWSTR prop,
+ UINT* rc)
+{
+ DWORD sz = 0;
+ LPWSTR str;
+ UINT r;
+
+ r = MSI_GetPropertyW(package, prop, NULL, &sz);
+ if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
+ {
+ if (rc)
+ *rc = r;
+ return NULL;
+ }
+ sz++;
+ str = HeapAlloc(GetProcessHeap(),0,sz*sizeof(WCHAR));
+ r = MSI_GetPropertyW(package, prop, str, &sz);
+ if (r != ERROR_SUCCESS)
+ {
+ HeapFree(GetProcessHeap(),0,str);
+ str = NULL;
+ }
+ if (rc)
+ *rc = r;
+ return str;
+}
+
inline static int get_loaded_component(MSIPACKAGE* package, LPCWSTR Component )
{
int rc = -1;
@@ -321,6 +376,7 @@
return rc;
}
+
static int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path)
{
DWORD i;
@@ -343,8 +399,8 @@
memset(&package->files[index],0,sizeof(MSIFILE));
- strcpyW(package->files[index].File,name);
- strcpyW(package->files[index].TargetPath,path);
+ package->files[index].File = dupstrW(name);
+ package->files[index].TargetPath = dupstrW(path);
package->files[index].Temporary = TRUE;
TRACE("Tracking tempfile (%s)\n",debugstr_w(package->files[index].File));
@@ -362,11 +418,103 @@
for (i = 0; i < package->loaded_files; i++)
{
if (package->files[i].Temporary)
+ {
+ TRACE("Cleaning up %s\n",debugstr_w(package->files[i].TargetPath));
DeleteFileW(package->files[i].TargetPath);
+ }
}
}
+/* Called when the package is being closed */
+extern void ACTION_free_package_structures( MSIPACKAGE* package)
+{
+ INT i;
+
+ TRACE("Freeing package action data\n");
+
+ /* No dynamic buffers in features */
+ if (package->features && package->loaded_features > 0)
+ HeapFree(GetProcessHeap(),0,package->features);
+
+ for (i = 0; i < package->loaded_folders; i++)
+ {
+ HeapFree(GetProcessHeap(),0,package->folders[i].Directory);
+ HeapFree(GetProcessHeap(),0,package->folders[i].TargetDefault);
+ HeapFree(GetProcessHeap(),0,package->folders[i].SourceDefault);
+ HeapFree(GetProcessHeap(),0,package->folders[i].ResolvedTarget);
+ HeapFree(GetProcessHeap(),0,package->folders[i].ResolvedSource);
+ HeapFree(GetProcessHeap(),0,package->folders[i].Property);
+ }
+ if (package->folders && package->loaded_folders > 0)
+ HeapFree(GetProcessHeap(),0,package->folders);
+
+ /* no dynamic buffers in components */
+ if (package->components && package->loaded_components > 0)
+ HeapFree(GetProcessHeap(),0,package->components);
+
+ for (i = 0; i < package->loaded_files; i++)
+ {
+ HeapFree(GetProcessHeap(),0,package->files[i].File);
+ HeapFree(GetProcessHeap(),0,package->files[i].FileName);
+ HeapFree(GetProcessHeap(),0,package->files[i].Version);
+ HeapFree(GetProcessHeap(),0,package->files[i].Language);
+ HeapFree(GetProcessHeap(),0,package->files[i].SourcePath);
+ HeapFree(GetProcessHeap(),0,package->files[i].TargetPath);
+ }
+
+ if (package->files && package->loaded_files > 0)
+ HeapFree(GetProcessHeap(),0,package->files);
+}
+
+static UINT ACTION_OpenQuery( MSIDATABASE *db, MSIQUERY **view, LPCWSTR fmt, ... )
+{
+ LPWSTR szQuery;
+ LPCWSTR p;
+ UINT sz, rc;
+ va_list va;
+
+ /* figure out how much space we need to allocate */
+ va_start(va, fmt);
+ sz = strlenW(fmt) + 1;
+ p = fmt;
+ while (*p)
+ {
+ p = strchrW(p, '%');
+ if (!p)
+ break;
+ p++;
+ switch (*p)
+ {
+ case 's': /* a string */
+ sz += strlenW(va_arg(va,LPCWSTR));
+ break;
+ case 'd':
+ case 'i': /* an integer -2147483648 seems to be longest */
+ sz += 3*sizeof(int);
+ (void)va_arg(va,int);
+ break;
+ case '%': /* a single % - leave it alone */
+ break;
+ default:
+ FIXME("Unhandled character type %c\n",*p);
+ }
+ p++;
+ }
+ va_end(va);
+
+ /* construct the string */
+ szQuery = HeapAlloc(GetProcessHeap(), 0, sz*sizeof(WCHAR));
+ va_start(va, fmt);
+ vsnprintfW(szQuery, sz, fmt, va);
+ va_end(va);
+
+ /* perform the query */
+ rc = MSI_DatabaseOpenViewW(db, szQuery, view);
+ HeapFree(GetProcessHeap(), 0, szQuery);
+ return rc;
+}
+
static void ui_progress(MSIPACKAGE *package, int a, int b, int c, int d )
{
MSIRECORD * row;
@@ -390,17 +538,14 @@
UINT rc;
MSIQUERY * view;
MSIRECORD * row = 0;
- static WCHAR *ActionFormat=NULL;
- static WCHAR LastAction[0x100] = {0};
- WCHAR Query[1024];
LPWSTR ptr;
- if (strcmpW(LastAction,action)!=0)
+ if (!package->LastAction || strcmpW(package->LastAction,action))
{
- sprintfW(Query,Query_t,action);
- rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
+ rc = ACTION_OpenQuery(package->db, &view, Query_t, action);
if (rc != ERROR_SUCCESS)
return;
+
rc = MSI_ViewExecute(view, 0);
if (rc != ERROR_SUCCESS)
{
@@ -422,18 +567,22 @@
return;
}
- if (ActionFormat)
- HeapFree(GetProcessHeap(),0,ActionFormat);
+ /* update the cached actionformat */
+ if (package->ActionFormat)
+ HeapFree(GetProcessHeap(),0,package->ActionFormat);
+ package->ActionFormat = load_dynamic_stringW(row,3);
- ActionFormat = load_dynamic_stringW(row,3);
- strcpyW(LastAction,action);
+ if (package->LastAction)
+ HeapFree(GetProcessHeap(),0,package->LastAction);
+ package->LastAction = dupstrW(action);
+
msiobj_release(&row->hdr);
MSI_ViewClose(view);
msiobj_release(&view->hdr);
}
message[0]=0;
- ptr = ActionFormat;
+ ptr = package->ActionFormat;
while (*ptr)
{
LPWSTR ptr2;
@@ -489,12 +638,10 @@
MSIQUERY * view;
MSIRECORD * row = 0;
WCHAR *ActionText=NULL;
- WCHAR Query[1024];
GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, format, timet, 0x100);
- sprintfW(Query,Query_t,action);
- rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
+ rc = ACTION_OpenQuery(package->db, &view, Query_t, action);
if (rc != ERROR_SUCCESS)
return;
rc = MSI_ViewExecute(view, 0);
@@ -555,6 +702,58 @@
msiobj_release(&row->hdr);
}
+/*
+ * build_directory_name()
+ *
+ * This function is to save messing round with directory names
+ * It handles adding backslashes between path segments,
+ * and can add \ at the end of the directory name if told to.
+ *
+ * It takes a variable number of arguments.
+ * It always allocates a new string for the result, so make sure
+ * to free the return value when finished with it.
+ *
+ * The first arg is the number of path segments that follow.
+ * The arguments following count are a list of path segments.
+ * A path segment may be NULL.
+ *
+ * Path segments will be added with a \ separating them.
+ * A \ will not be added after the last segment, however if the
+ * last segment is NULL, then the last character will be a \
+ *
+ */
+static LPWSTR build_directory_name(DWORD count, ...)
+{
+ DWORD sz = 1, i;
+ LPWSTR dir;
+ va_list va;
+
+ va_start(va,count);
+ for(i=0; i<count; i++)
+ {
+ LPCWSTR str = va_arg(va,LPCWSTR);
+ if (str)
+ sz += strlenW(str) + 1;
+ }
+ va_end(va);
+
+ dir = HeapAlloc(GetProcessHeap(), 0, sz*sizeof(WCHAR));
+ dir[0]=0;
+
+ va_start(va,count);
+ for(i=0; i<count; i++)
+ {
+ LPCWSTR str = va_arg(va,LPCWSTR);
+ if (!str)
+ continue;
+ strcatW(dir, str);
+ if( ((i+1)!=count) && dir[strlenW(dir)-1]!='\\')
+ strcatW(dir, cszbs);
+ }
+ return dir;
+}
+
+
/****************************************************
* TOP level entry points
*****************************************************/
@@ -569,23 +768,23 @@
if (szPackagePath)
{
- LPWSTR p;
- WCHAR check[MAX_PATH];
- WCHAR pth[MAX_PATH];
- DWORD size;
+ LPWSTR p, check, path;
- strcpyW(pth,szPackagePath);
- p = strrchrW(pth,'\\');
+ path = dupstrW(szPackagePath);
+ p = strrchrW(path,'\\');
if (p)
{
p++;
*p=0;
}
- size = MAX_PATH;
- if (MSI_GetPropertyW(package,cszSourceDir,check,&size)
- != ERROR_SUCCESS )
- MSI_SetPropertyW(package, cszSourceDir, pth);
+ check = load_dynamic_property(package, cszSourceDir,NULL);
+ if (!check)
+ MSI_SetPropertyW(package, cszSourceDir, path);
+ else
+ HeapFree(GetProcessHeap(), 0, check);
+
+ HeapFree(GetProcessHeap(), 0, path);
}
if (szCommandLine)
@@ -595,8 +794,8 @@
while (*ptr)
{
- WCHAR prop[0x100];
- WCHAR val[0x100];
+ WCHAR *prop = NULL;
+ WCHAR *val = NULL;
TRACE("Looking at %s\n",debugstr_w(ptr));
@@ -607,10 +806,13 @@
DWORD len = 0;
while (*ptr == ' ') ptr++;
- strncpyW(prop,ptr,ptr2-ptr);
- prop[ptr2-ptr]=0;
+ len = ptr2-ptr;
+ prop = HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR));
+ strncpyW(prop,ptr,len);
+ prop[len]=0;
ptr2++;
-
+
+ len = 0;
ptr = ptr2;
while (*ptr && (quote || (!quote && *ptr!=' ')))
{
@@ -625,14 +827,18 @@
ptr2++;
len -= 2;
}
+ val = HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR));
strncpyW(val,ptr2,len);
- val[len]=0;
+ val[len] = 0;
if (strlenW(prop) > 0)
{
- TRACE("Found commandline property (%s) = (%s)\n", debugstr_w(prop), debugstr_w(val));
+ TRACE("Found commandline property (%s) = (%s)\n",
+ debugstr_w(prop), debugstr_w(val));
MSI_SetPropertyW(package,prop,val);
}
+ HeapFree(GetProcessHeap(),0,val);
+ HeapFree(GetProcessHeap(),0,prop);
}
ptr++;
}
@@ -653,10 +859,93 @@
else
rc = ACTION_ProcessExecSequence(package,FALSE);
+ /* process the ending type action */
+ if (rc == ERROR_SUCCESS)
+ rc = ACTION_PerformActionSequence(package,-1);
+ else if (rc == ERROR_FUNCTION_FAILED)
+ rc = ACTION_PerformActionSequence(package,-3);
+
return rc;
}
+static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq)
+{
+ MSIQUERY * view;
+ UINT rc;
+ WCHAR buffer[0x100];
+ DWORD sz = 0x100;
+ MSIRECORD * row = 0;
+ static const WCHAR ExecSeqQuery[] = {
+ 's','e','l','e','c','t',' ','*',' ',
+ 'f','r','o','m',' ',
+ 'I','n','s','t','a','l','l','E','x','e','c','u','t','e',
+ 'S','e','q','u','e','n','c','e',' ',
+ 'w','h','e','r','e',' ','S','e','q','u','e','n','c','e',' ',
+ '=',' ','%','i',0};
+ rc = ACTION_OpenQuery(package->db, &view, ExecSeqQuery, seq);
+
+ if (rc == ERROR_SUCCESS)
+ {
+ rc = MSI_ViewExecute(view, 0);
+
+ if (rc != ERROR_SUCCESS)
+ {
+ MSI_ViewClose(view);
+ msiobj_release(&view->hdr);
+ goto end;
+ }
+
+ TRACE("Running the actions\n");
+
+ rc = MSI_ViewFetch(view,&row);
+ if (rc != ERROR_SUCCESS)
+ {
+ rc = ERROR_SUCCESS;
+ goto end;
+ }
+
+ /* check conditions */
+ if (!MSI_RecordIsNull(row,2))
+ {
+ LPWSTR cond = NULL;
+ cond = load_dynamic_stringW(row,2);
+
+ if (cond)
+ {
+ /* this is a hack to skip errors in the condition code */
+ if (MSI_EvaluateConditionW(package, cond) == MSICONDITION_FALSE)
+ {
+ HeapFree(GetProcessHeap(),0,cond);
+ msiobj_release(&row->hdr);
+ goto end;
+ }
+ else
+ HeapFree(GetProcessHeap(),0,cond);
+ }
+ }
+
+ sz=0x100;
+ rc = MSI_RecordGetStringW(row,1,buffer,&sz);
+ if (rc != ERROR_SUCCESS)
+ {
+ ERR("Error is %x\n",rc);
+ msiobj_release(&row->hdr);
+ goto end;
+ }
+
+ rc = ACTION_PerformAction(package,buffer);
+ msiobj_release(&row->hdr);
+end:
+ MSI_ViewClose(view);
+ msiobj_release(&view->hdr);
+ }
+ else
+ rc = ERROR_SUCCESS;
+
+ return rc;
+}
+
static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran)
{
MSIQUERY * view;
@@ -669,7 +958,6 @@
'w','h','e','r','e',' ','S','e','q','u','e','n','c','e',' ',
'>',' ','%','i',' ','o','r','d','e','r',' ',
'b','y',' ','S','e','q','u','e','n','c','e',0 };
- WCHAR Query[1024];
MSIRECORD * row = 0;
static const WCHAR IVQuery[] = {
's','e','l','e','c','t',' ','S','e','q','u','e','n','c','e',' ',
@@ -678,11 +966,11 @@
'w','h','e','r','e',' ','A','c','t','i','o','n',' ','=',' ',
'`','I','n','s','t','a','l','l','V','a','l','i','d','a','t','e','`',
0};
+ INT seq = 0;
+ /* get the sequence number */
if (UIran)
{
- INT seq = 0;
-
rc = MSI_DatabaseOpenViewW(package->db, IVQuery, &view);
if (rc != ERROR_SUCCESS)
return rc;
@@ -704,12 +992,9 @@
msiobj_release(&row->hdr);
MSI_ViewClose(view);
msiobj_release(&view->hdr);
- sprintfW(Query,ExecSeqQuery,seq);
}
- else
- sprintfW(Query,ExecSeqQuery,0);
-
- rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
+
+ rc = ACTION_OpenQuery(package->db, &view, ExecSeqQuery, seq);
if (rc == ERROR_SUCCESS)
{
rc = MSI_ViewExecute(view, 0);
@@ -721,7 +1006,7 @@
goto end;
}
- TRACE("Running the actions \n");
+ TRACE("Running the actions\n");
while (1)
{
@@ -900,7 +1185,6 @@
TRACE("Performing action (%s)\n",debugstr_w(action));
ui_actioninfo(package, action, TRUE, 0);
ui_actionstart(package, action);
- ui_progress(package,2,1,0,0);
/* pre install, setup and configuration block */
if (strcmpW(action,szLaunchConditions)==0)
@@ -961,21 +1245,16 @@
UINT rc = ERROR_SUCCESS;
MSIQUERY * view;
MSIRECORD * row = 0;
- WCHAR ExecSeqQuery[1024] =
+ static const WCHAR ExecSeqQuery[] =
{'s','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','C','u','s','t','o'
-,'m','A','c','t','i','o','n',' ','w','h','e','r','e',' ','`','A','c','t','i'
-,'o','n','`',' ','=',' ','`',0};
- static const WCHAR end[]={'`',0};
+ ,'m','A','c','t','i','o','n',' ','w','h','e','r','e',' ','`','A','c','t','i'
+ ,'o','n','`',' ','=',' ','`','%','s','`',0};
UINT type;
LPWSTR source;
LPWSTR target;
WCHAR *deformated=NULL;
- strcatW(ExecSeqQuery,action);
- strcatW(ExecSeqQuery,end);
-
- rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
-
+ rc = ACTION_OpenQuery(package->db, &view, ExecSeqQuery, action);
if (rc != ERROR_SUCCESS)
return rc;
@@ -1022,6 +1301,10 @@
rc = HANDLE_CustomType34(package,source,target,type);
break;
case 35: /* Directory set with formatted text. */
+ deformat_string(package,target,&deformated);
+ MSI_SetTargetPathW(package, source, deformated);
+ HeapFree(GetProcessHeap(),0,deformated);
+ break;
case 51: /* Property set with formatted text. */
deformat_string(package,target,&deformated);
rc = MSI_SetPropertyW(package,source,deformated);
@@ -1063,10 +1346,9 @@
UINT rc;
MSIQUERY * view;
MSIRECORD * row = 0;
- WCHAR Query[1024] =
+ static const WCHAR fmt[] =
{'s','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','B','i'
-,'n','a','r','y',' ','w','h','e','r','e',' ','N','a','m','e','=','`',0};
- static const WCHAR end[]={'`',0};
+,'n','a','r','y',' ','w','h','e','r','e',' ','N','a','m','e','=','`','%','s','`',0};
HANDLE the_file;
CHAR buffer[1024];
@@ -1079,10 +1361,7 @@
if (the_file == INVALID_HANDLE_VALUE)
return ERROR_FUNCTION_FAILED;
- strcatW(Query,source);
- strcatW(Query,end);
-
- rc = MSI_DatabaseOpenViewW( package->db, Query, &view);
+ rc = ACTION_OpenQuery(package->db, &view, fmt, source);
if (rc != ERROR_SUCCESS)
return rc;
@@ -1127,66 +1406,82 @@
return ERROR_SUCCESS;
}
-
typedef UINT __stdcall CustomEntry(MSIHANDLE);
typedef struct
{
MSIPACKAGE *package;
- WCHAR target[MAX_PATH];
- WCHAR source[MAX_PATH];
+ WCHAR *target;
+ WCHAR *source;
} thread_struct;
-#if 0
-static DWORD WINAPI DllThread(LPVOID info)
+static DWORD WINAPI ACTION_CallDllFunction(thread_struct *stuff)
{
- HANDLE DLL;
+ HANDLE hModule;
LPSTR proc;
- thread_struct *stuff;
CustomEntry *fn;
-
- stuff = (thread_struct*)info;
- TRACE("Asynchronous start (%s, %s) \n", debugstr_w(stuff->source),
+ TRACE("calling function (%s, %s) \n", debugstr_w(stuff->source),
debugstr_w(stuff->target));
- DLL = LoadLibraryW(stuff->source);
- if (DLL)
+ hModule = LoadLibraryW(stuff->source);
+ if (hModule)
{
proc = strdupWtoA( stuff->target );
- fn = (CustomEntry*)GetProcAddress(DLL,proc);
+ fn = (CustomEntry*)GetProcAddress(hModule,proc);
if (fn)
{
MSIHANDLE hPackage;
MSIPACKAGE *package = stuff->package;
- TRACE("Calling function\n");
+ TRACE("Calling function %s\n", proc);
hPackage = msiobj_findhandle( &package->hdr );
- if( !hPackage )
+ if (hPackage )
+ {
+ fn(hPackage);
+ msiobj_release( &package->hdr );
+ }
+ else
ERR("Handle for object %p not found\n", package );
- fn(hPackage);
- msiobj_release( &package->hdr );
}
else
ERR("Cannot load functon\n");
HeapFree(GetProcessHeap(),0,proc);
- FreeLibrary(DLL);
+ FreeLibrary(hModule);
}
else
ERR("Unable to load library\n");
msiobj_release( &stuff->package->hdr );
- HeapFree( GetProcessHeap(), 0, info );
+ HeapFree(GetProcessHeap(),0,stuff->source);
+ HeapFree(GetProcessHeap(),0,stuff->target);
+ HeapFree(GetProcessHeap(), 0, stuff);
return 0;
}
-#endif
+static DWORD WINAPI DllThread(LPVOID info)
+{
+ thread_struct *stuff;
+ DWORD rc = 0;
+
+ TRACE("MSI Thread (0x%lx) started for custom action\n",
+ GetCurrentThreadId());
+
+ stuff = (thread_struct*)info;
+ rc = ACTION_CallDllFunction(stuff);
+
+ TRACE("MSI Thread (0x%lx) finished\n",GetCurrentThreadId());
+ /* clse all handles for this thread */
+ MsiCloseAllHandles();
+ return rc;
+}
+
static UINT HANDLE_CustomType1(MSIPACKAGE *package, const LPWSTR source,
const LPWSTR target, const INT type)
{
WCHAR tmp_file[MAX_PATH];
- CustomEntry *fn;
- HANDLE DLL;
- LPSTR proc;
+ thread_struct *info;
+ DWORD ThreadId;
+ HANDLE ThreadHandle;
store_binary_to_temp(package, source, tmp_file);
@@ -1199,76 +1494,57 @@
strcatW(tmp_file,dot);
}
- if (type & 0xc0)
- {
- /* DWORD ThreadId; */
- thread_struct *info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info) );
+ info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info) );
+ msiobj_addref( &package->hdr );
+ info->package = package;
+ info->target = dupstrW(target);
+ info->source = dupstrW(tmp_file);
- /* msiobj_addref( &package->hdr ); */
- info->package = package;
- strcpyW(info->target,target);
- strcpyW(info->source,tmp_file);
- TRACE("Start Asynchronous execution\n");
- FIXME("DATABASE NOT THREADSAFE... not starting\n");
- /* CreateThread(NULL,0,DllThread,(LPVOID)&info,0,&ThreadId); */
- /* FIXME: release the package if the CreateThread fails */
- HeapFree( GetProcessHeap(), 0, info );
- return ERROR_SUCCESS;
- }
-
- DLL = LoadLibraryW(tmp_file);
- if (DLL)
- {
- proc = strdupWtoA( target );
- fn = (CustomEntry*)GetProcAddress(DLL,proc);
- if (fn)
- {
- MSIHANDLE hPackage;
+ ThreadHandle = CreateThread(NULL,0,DllThread,(LPVOID)info,0,&ThreadId);
- TRACE("Calling function\n");
- hPackage = msiobj_findhandle( &package->hdr );
- if( !hPackage )
- ERR("Handle for object %p not found\n", package );
- fn(hPackage);
- msiobj_release( &package->hdr );
- }
- else
- ERR("Cannot load functon\n");
+ if (!(type & 0xc0))
+ WaitForSingleObject(ThreadHandle,INFINITE);
- HeapFree(GetProcessHeap(),0,proc);
- FreeLibrary(DLL);
- }
- else
- ERR("Unable to load library\n");
-
[truncated at 1000 lines; 8611 more skipped]