MSI: handle custom actions type 1 and 2
Mike McCormack
mike at codeweavers.com
Mon Jun 28 19:03:09 CDT 2004
ChangeLog:
<aric at codeweavers.com>
* handle custom actions type 1 and 2
-------------- next part --------------
diff -ur dlls/msi.old/action.c dlls/msi/action.c
--- dlls/msi.old/action.c 2004-06-28 18:59:09.000000000 -0500
+++ dlls/msi/action.c 2004-06-28 19:00:11.000000000 -0500
@@ -78,6 +78,12 @@
static UINT ACTION_WriteRegistryValues(MSIHANDLE hPackage);
static UINT ACTION_CustomAction(MSIHANDLE hPackage,const WCHAR *action);
+static UINT HANDLE_CustomType1(MSIHANDLE hPackage, const LPWSTR source,
+ const LPWSTR target, const INT type);
+static UINT HANDLE_CustomType2(MSIHANDLE hPackage, const LPWSTR source,
+ const LPWSTR target, const INT type);
+
+
static UINT set_property(MSIHANDLE hPackage, const WCHAR* prop,
const WCHAR* value);
UINT get_property(MSIHANDLE hPackage, const WCHAR* prop, WCHAR* value,
@@ -101,6 +107,18 @@
/********************************************************
* helper functions to get around current HACKS and such
********************************************************/
+inline static char *strdupWtoA( const WCHAR *str )
+{
+ char *ret = NULL;
+ if (str)
+ {
+ DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL
+);
+ if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
+ WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
+ }
+ return ret;
+}
static VOID blitz_propertytable()
{
@@ -248,7 +266,8 @@
{'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0};
static const WCHAR WF[] =
{'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
-
+ static const WCHAR TF[]=
+{'T','e','m','p','F','o','l','d','e','r',0};
/* Not yet set ... but needed by iTunes
*
@@ -266,7 +285,6 @@
StartupFolder
System16Folder
System64Folder
-TempFolder
TemplateFolder
*/
@@ -316,6 +334,9 @@
SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
strcatW(pth,cszbs);
set_property(hPackage, WF, pth);
+
+ GetTempPathW(MAX_PATH,pth);
+ set_property(hPackage, TF, pth);
}
@@ -482,8 +503,67 @@
if (strcmpW(action,szWriteRegistryValues)==0)
return ACTION_WriteRegistryValues(hPackage);
/*
- .
- .
+ Current called during itunes but unimplemented
+
+ AppSearch
+ LaunchConditions
+ FindRelatedProducts
+ CostInitialize
+ MigrateFeatureStates
+ ResolveSource (sets SourceDir)
+ FileCost
+ ValidateProductID (sets ProductID)
+ IsolateComponents (Empty)
+ SetODBCFolders
+ MigrateFeatureStates
+ InstallValidate
+ RemoveExistingProducts
+ InstallInitialize
+ AllocateRegistrySpace
+ ProcessComponents
+ UnpublishComponents
+ UnpublishFeatures
+ StopServices
+ DeleteServices
+ UnregisterComPlus
+ SelfUnregModules (Empty)
+ UnregisterTypeLibraries
+ RemoveODBC
+ UnregisterFonts
+ RemoveRegistryValues
+ UnregisterClassInfo
+ UnregisterExtensionInfo
+ UnregisterProgIdInfo
+ UnregisterMIMEInfo
+ RemoveIniValues
+ RemoveShortcuts
+ RemoveEnviromentStrings
+ RemoveDuplicateFiles
+ RemoveFiles (Empty)
+ MoveFiles (Empty)
+ RemoveRegistryValues (Empty)
+ SelfRegModules (Empty)
+ RemoveFolders
+ PatchFiles
+ BindImage (Empty)
+ CreateShortcuts (would be nice to have soon)
+ RegisterClassInfo
+ RegisterExtensionInfo (Empty)
+ RegisterProgIdInfo (Lots to do)
+ RegisterMIMEInfo (Empty)
+ WriteIniValues (Empty)
+ WriteEnvironmentStrings (Empty)
+ RegisterFonts(Empty)
+ InstallODBC
+ RegisterTypeLibraries
+ SelfRegModules
+ RegisterComPlus
+ RegisterUser
+ RegisterProduct
+ PublishComponents
+ PublishFeatures
+ PublishProduct
+ InstallFinalize
.
*/
if (ACTION_CustomAction(hPackage,action) != ERROR_SUCCESS)
@@ -531,23 +611,35 @@
return rc;
}
- TRACE("Handling custom action %s\n",debugstr_w(action));
type = MsiRecordGetInteger(row,2);
+ sz=0x100;
+ MsiRecordGetStringW(row,3,source,&sz);
+ sz=0x200;
+ MsiRecordGetStringW(row,4,target,&sz);
+
+ TRACE("Handling custom action %s (%x %s %s)\n",debugstr_w(action),type,
+ debugstr_w(source), debugstr_w(target));
+
+ /* we are ignoring ALOT of flags and important syncornication stuff */
switch (type & CUSTOM_ACTION_TYPE_MASK)
{
+ case 1: /* DLL file stored in a Binary table stream */
+ rc = HANDLE_CustomType1(hPackage,source,target,type);
+ break;
+ case 2: /* Exe file stored in a Binary table strem */
+ rc = HANDLE_CustomType2(hPackage,source,target,type);
+ break;
case 35: /* Directory set with formatted text. */
case 51: /* Property set with formatted text. */
- sz=0x100;
- MsiRecordGetStringW(row,3,source,&sz);
- sz=0x200;
- MsiRecordGetStringW(row,4,target,&sz);
deformat_string(hPackage,target,&deformated);
set_property(hPackage,source,deformated);
HeapFree(GetProcessHeap(),0,deformated);
break;
default:
- ERR("UNHANDLED ACTION TYPE %i\n",type & CUSTOM_ACTION_TYPE_MASK);
+ ERR("UNHANDLED ACTION TYPE %i (%s %s)\n",
+ type & CUSTOM_ACTION_TYPE_MASK, debugstr_w(source),
+ debugstr_w(target));
}
MsiCloseHandle(row);
@@ -556,6 +648,170 @@
return rc;
}
+static UINT store_binary_to_temp(MSIHANDLE hPackage, const LPWSTR source,
+ LPWSTR tmp_file)
+{
+ static const WCHAR TF[]= {'T','e','m','p','F','o','l','d','e','r',0};
+ DWORD sz=MAX_PATH;
+
+ if (get_property(hPackage, TF,tmp_file, &sz) != ERROR_SUCCESS)
+ GetTempPathW(MAX_PATH,tmp_file);
+
+ strcatW(tmp_file,source);
+
+ if (GetFileAttributesW(tmp_file) != INVALID_FILE_ATTRIBUTES)
+ {
+ TRACE("File already exists\n");
+ return ERROR_SUCCESS;
+ }
+ else
+ {
+ /* write out the file */
+ UINT rc;
+ MSIHANDLE view;
+ MSIHANDLE row = 0;
+ WCHAR Query[1024] =
+ {'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};
+ HANDLE the_file;
+ CHAR buffer[1024];
+
+ the_file = CreateFileW(tmp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (the_file == INVALID_HANDLE_VALUE)
+ return ERROR_FUNCTION_FAILED;
+
+ strcatW(Query,source);
+ strcatW(Query,end);
+ rc = MsiDatabaseOpenViewW(hPackage, Query, &view);
+ if (rc != ERROR_SUCCESS)
+ return rc;
+
+ rc = MsiViewExecute(view, 0);
+ if (rc != ERROR_SUCCESS)
+ {
+ MsiViewClose(view);
+ MsiCloseHandle(view);
+ return rc;
+ }
+
+ rc = MsiViewFetch(view,&row);
+ if (rc != ERROR_SUCCESS)
+ {
+ MsiViewClose(view);
+ MsiCloseHandle(view);
+ return rc;
+ }
+
+ do
+ {
+ DWORD write;
+ sz = 1024;
+ rc = MsiRecordReadStream(row,2,buffer,&sz);
+ if (rc != ERROR_SUCCESS)
+ {
+ ERR("Failed to get stream\n");
+ CloseHandle(the_file);
+ DeleteFileW(tmp_file);
+ break;
+ }
+ WriteFile(the_file,buffer,sz,&write,NULL);
+ } while (sz == 1024);
+
+ CloseHandle(the_file);
+
+ MsiCloseHandle(row);
+ MsiViewClose(view);
+ MsiCloseHandle(view);
+ }
+
+ return ERROR_SUCCESS;
+}
+
+
+typedef UINT CustomEntry(MSIHANDLE);
+
+static UINT HANDLE_CustomType1(MSIHANDLE hPackage, const LPWSTR source,
+ const LPWSTR target, const INT type)
+{
+ WCHAR tmp_file[MAX_PATH];
+ CustomEntry *fn;
+ HANDLE DLL;
+ LPSTR proc;
+
+ store_binary_to_temp(hPackage, source, tmp_file);
+
+ TRACE("Calling function %s from %s\n",debugstr_w(target),
+ debugstr_w(tmp_file));
+
+ if (type & 0xc0)
+ {
+ ERR("Asyncronious execution.. UNHANDLED\n");
+ return ERROR_SUCCESS;
+ }
+
+ DLL = LoadLibraryW(tmp_file);
+ if (DLL)
+ {
+ proc = strdupWtoA( target );
+ fn = (CustomEntry*)GetProcAddress(DLL,proc);
+ if (fn)
+ {
+ TRACE("Calling function\n");
+ fn(hPackage);
+ }
+ else
+ ERR("Cannot load functon\n");
+
+ HeapFree(GetProcessHeap(),0,proc);
+ FreeLibrary(DLL);
+ }
+ else
+ ERR("Unable to load library\n");
+
+ return ERROR_SUCCESS;
+}
+
+static UINT HANDLE_CustomType2(MSIHANDLE hPackage, const LPWSTR source,
+ const LPWSTR target, const INT type)
+{
+ WCHAR tmp_file[MAX_PATH*2];
+ STARTUPINFOW si;
+ PROCESS_INFORMATION info;
+ BOOL rc;
+ WCHAR *deformated;
+ static const WCHAR c_collen[] = {'C',':','\\',0};
+ static const WCHAR spc[] = {' ',0};
+
+ memset(&si,0,sizeof(STARTUPINFOW));
+ memset(&info,0,sizeof(PROCESS_INFORMATION));
+
+ store_binary_to_temp(hPackage, source, tmp_file);
+
+ strcatW(tmp_file,spc);
+ deformat_string(hPackage,target,&deformated);
+ strcatW(tmp_file,deformated);
+
+ HeapFree(GetProcessHeap(),0,deformated);
+
+ TRACE("executing exe %s \n",debugstr_w(tmp_file));
+
+ rc = CreateProcessW(NULL, tmp_file, NULL, NULL, FALSE, 0, NULL,
+ c_collen, &si, &info);
+
+ if ( !rc )
+ {
+ ERR("Unable to execute command\n");
+ return ERROR_SUCCESS;
+ }
+
+ if (!(type & 0xc0))
+ WaitForSingleObject(info.hProcess,INFINITE);
+
+ return ERROR_SUCCESS;
+}
/***********************************************************************
* create_full_pathW
@@ -960,18 +1216,6 @@
return rc;
}
-inline static char *strdupWtoA( const WCHAR *str )
-{
- char *ret = NULL;
- if (str)
- {
- DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL
-);
- if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
- WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
- }
- return ret;
-}
/***********************************************************************
* extract_cabinet_file
diff -ur dlls/msi.old/msi.c dlls/msi/msi.c
--- dlls/msi.old/msi.c 2004-06-28 18:59:08.000000000 -0500
+++ dlls/msi/msi.c 2004-06-28 19:00:11.000000000 -0500
@@ -1343,3 +1343,11 @@
msihandle_addref(hInstall);
return hInstall;
}
+
+UINT WINAPI MsiEnumRelatedProductsA (LPCSTR lpUpgradeCode, DWORD dwReserved,
+ DWORD iProductIndex, LPSTR lpProductBuf)
+{
+ FIXME("STUB: (%s, %li %li %s)\n",lpUpgradeCode, dwReserved, iProductIndex,
+ lpProductBuf);
+ return ERROR_CALL_NOT_IMPLEMENTED;
+}
diff -ur dlls/msi.old/msi.spec dlls/msi/msi.spec
--- dlls/msi.old/msi.spec 2004-06-28 18:59:08.000000000 -0500
+++ dlls/msi/msi.spec 2004-06-28 19:00:11.000000000 -0500
@@ -201,7 +201,7 @@
201 stub MsiDecomposeDescriptorW
202 stub MsiProvideQualifiedComponentExA
203 stub MsiProvideQualifiedComponentExW
-204 stub MsiEnumRelatedProductsA
+204 stdcall MsiEnumRelatedProductsA(str long long str)
205 stub MsiEnumRelatedProductsW
206 stub MsiSetFeatureAttributesA
207 stub MsiSetFeatureAttributesW
More information about the wine-patches
mailing list