Implemented CreateShortcut and PublishProduct.

This commit is contained in:
Aric Stewart 2004-07-06 19:00:23 +00:00 committed by Alexandre Julliard
parent 24e9a34494
commit 2cf222f9b7
2 changed files with 351 additions and 23 deletions

View File

@ -145,6 +145,8 @@ static UINT ACTION_ProcessComponents(MSIHANDLE hPackage);
static UINT ACTION_RegisterTypeLibraries(MSIHANDLE hPackage);
static UINT ACTION_RegisterClassInfo(MSIHANDLE hPackage);
static UINT ACTION_RegisterProgIdInfo(MSIHANDLE hPackage);
static UINT ACTION_CreateShortcuts(MSIHANDLE hPackage);
static UINT ACTION_PublishProduct(MSIHANDLE hPackage);
static UINT HANDLE_CustomType1(MSIHANDLE hPackage, const LPWSTR source,
const LPWSTR target, const INT type);
@ -199,6 +201,10 @@ const static WCHAR szRegisterClassInfo[] =
{'R','e','g','i','s','t','e','r','C','l','a','s','s','I','n','f','o',0};
const static WCHAR szRegisterProgIdInfo[] =
{'R','e','g','i','s','t','e','r','P','r','o','g','I','d','I','n','f','o',0};
const static WCHAR szCreateShortcuts[] =
{'C','r','e','a','t','e','S','h','o','r','t','c','u','t','s',0};
const static WCHAR szPublishProduct[] =
{'P','u','b','l','i','s','h','P','r','o','d','u','c','t',0};
/********************************************************
* helper functions to get around current HACKS and such
@ -852,12 +858,15 @@ UINT ACTION_PerformAction(MSIHANDLE hPackage, const WCHAR *action)
rc = ACTION_RegisterClassInfo(hPackage);
else if (strcmpW(action,szRegisterProgIdInfo)==0)
rc = ACTION_RegisterProgIdInfo(hPackage);
else if (strcmpW(action,szCreateShortcuts)==0)
rc = ACTION_CreateShortcuts(hPackage);
else if (strcmpW(action,szPublishProduct)==0)
rc = ACTION_PublishProduct(hPackage);
/*
Called during itunes but unimplemented and seem important
ResolveSource (sets SourceDir)
CreateShortcuts (would be nice to have soon)
RegisterProduct
InstallFinalize
*/
@ -3049,6 +3058,13 @@ static void resolve_keypath(MSIHANDLE hPackage, MSIPACKAGE* package, INT
}
}
/*
* Ok further analysis makes me think that this work is
* actually done in the PublishComponents and PublishFeatures
* step. And not here. It appears like the keypath and all that is
* resolved in this step, however actaully written in the Publish steps.
* But we will leave it here for now
*/
static UINT ACTION_ProcessComponents(MSIHANDLE hPackage)
{
MSIPACKAGE* package;
@ -3712,6 +3728,7 @@ static UINT ACTION_RegisterProgIdInfo(MSIHANDLE hPackage)
}
register_progid(hPackage,row,clsid);
ui_actiondata(hPackage,szRegisterProgIdInfo,row);
MsiCloseHandle(row);
}
@ -3720,6 +3737,319 @@ static UINT ACTION_RegisterProgIdInfo(MSIHANDLE hPackage)
return rc;
}
static UINT build_icon_path(MSIHANDLE hPackage, LPCWSTR icon_name,
LPWSTR FilePath)
{
WCHAR ProductCode[0x100];
WCHAR SystemFolder[MAX_PATH];
DWORD sz;
static const WCHAR szInstaller[] =
{'I','n','s','t','a','l','l','e','r','\\',0};
static const WCHAR szProductCode[] =
{'P','r','o','d','u','c','t','C','o','d','e',0};
static const WCHAR szFolder[] =
{'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
sz = 0x100;
MsiGetPropertyW(hPackage,szProductCode,ProductCode,&sz);
if (strlenW(ProductCode)==0)
return ERROR_FUNCTION_FAILED;
sz = MAX_PATH;
MsiGetPropertyW(hPackage,szFolder,SystemFolder,&sz);
strcatW(SystemFolder,szInstaller);
strcatW(SystemFolder,ProductCode);
create_full_pathW(SystemFolder);
strcpyW(FilePath,SystemFolder);
strcatW(FilePath,cszbs);
strcatW(FilePath,icon_name);
return ERROR_SUCCESS;
}
static UINT ACTION_CreateShortcuts(MSIHANDLE hPackage)
{
UINT rc;
MSIHANDLE view;
MSIHANDLE row = 0;
static const CHAR *Query = "SELECT * from Shortcut";
MSIPACKAGE* package;
IShellLinkW *sl;
IPersistFile *pf;
HRESULT res;
package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
if (!package)
return ERROR_INVALID_HANDLE;
res = CoInitialize( NULL );
if (FAILED (res))
{
ERR("CoInitialize failed\n");
return ERROR_FUNCTION_FAILED;
}
rc = MsiDatabaseOpenViewA(package->db, Query, &view);
if (rc != ERROR_SUCCESS)
return rc;
rc = MsiViewExecute(view, 0);
if (rc != ERROR_SUCCESS)
{
MsiViewClose(view);
MsiCloseHandle(view);
return rc;
}
while (1)
{
WCHAR target_file[MAX_PATH];
WCHAR buffer[0x1000];
DWORD sz;
DWORD index;
static const WCHAR szlnk[]={'.','l','n','k',0};
rc = MsiViewFetch(view,&row);
if (rc != ERROR_SUCCESS)
{
rc = ERROR_SUCCESS;
break;
}
sz = 0x1000;
MsiRecordGetStringW(row,4,buffer,&sz);
index = get_loaded_component(package,buffer);
if (index < 0)
{
MsiCloseHandle(row);
continue;
}
if (!package->components[index].Enabled ||
!package->components[index].FeatureState)
{
TRACE("Skipping shortcut creation due to disabled component\n");
MsiCloseHandle(row);
continue;
}
ui_actiondata(hPackage,szCreateShortcuts,row);
res = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
&IID_IShellLinkW, (LPVOID *) &sl );
if (FAILED(res))
{
ERR("Is IID_IShellLink\n");
MsiCloseHandle(row);
continue;
}
res = IShellLinkW_QueryInterface( sl, &IID_IPersistFile,(LPVOID*) &pf );
if( FAILED( res ) )
{
ERR("Is IID_IPersistFile\n");
MsiCloseHandle(row);
continue;
}
sz = 0x1000;
MsiRecordGetStringW(row,2,buffer,&sz);
resolve_folder(hPackage, buffer,target_file,FALSE,FALSE,NULL);
sz = 0x1000;
MsiRecordGetStringW(row,3,buffer,&sz);
reduce_to_longfilename(buffer);
strcatW(target_file,buffer);
if (!strchrW(target_file,'.'))
strcatW(target_file,szlnk);
sz = 0x1000;
MsiRecordGetStringW(row,5,buffer,&sz);
if (strchrW(buffer,'['))
{
LPWSTR deformated;
deformat_string(hPackage,buffer,&deformated);
IShellLinkW_SetPath(sl,deformated);
HeapFree(GetProcessHeap(),0,deformated);
}
else
{
FIXME("UNHANDLED shortcut format, advertised shortcut\n");
IPersistFile_Release( pf );
IShellLinkW_Release( sl );
MsiCloseHandle(row);
continue;
}
if (!MsiRecordIsNull(row,6))
{
LPWSTR deformated;
sz = 0x1000;
MsiRecordGetStringW(row,6,buffer,&sz);
deformat_string(hPackage,buffer,&deformated);
IShellLinkW_SetArguments(sl,deformated);
HeapFree(GetProcessHeap(),0,deformated);
}
if (!MsiRecordIsNull(row,7))
{
LPWSTR deformated;
sz = 0;
MsiRecordGetStringW(row,7,NULL,&sz);
sz++;
deformated = HeapAlloc(GetProcessHeap(),0,sz * sizeof(WCHAR));
MsiRecordGetStringW(row,7,deformated,&sz);
IShellLinkW_SetDescription(sl,deformated);
HeapFree(GetProcessHeap(),0,deformated);
}
if (!MsiRecordIsNull(row,8))
IShellLinkW_SetHotkey(sl,MsiRecordGetInteger(row,8));
if (!MsiRecordIsNull(row,9))
{
WCHAR Path[MAX_PATH];
INT index;
sz = 0x1000;
MsiRecordGetStringW(row,9,buffer,&sz);
build_icon_path(hPackage,buffer,Path);
index = MsiRecordGetInteger(row,10);
IShellLinkW_SetIconLocation(sl,Path,index);
}
if (!MsiRecordIsNull(row,11))
IShellLinkW_SetShowCmd(sl,MsiRecordGetInteger(row,11));
if (!MsiRecordIsNull(row,12))
{
WCHAR Path[MAX_PATH];
sz = 0x1000;
MsiRecordGetStringW(row,12,buffer,&sz);
resolve_folder(hPackage, buffer, Path, FALSE, FALSE, NULL);
IShellLinkW_SetWorkingDirectory(sl,Path);
}
TRACE("Writing shortcut to %s\n",debugstr_w(target_file));
IPersistFile_Save(pf,target_file,FALSE);
IPersistFile_Release( pf );
IShellLinkW_Release( sl );
MsiCloseHandle(row);
}
MsiViewClose(view);
MsiCloseHandle(view);
CoUninitialize();
return rc;
}
/*
* 99% of the work done here is only done for
* advertised installs. However this is where the
* Icon table is processed and written out
* so that is waht i am going to do here
*/
static UINT ACTION_PublishProduct(MSIHANDLE hPackage)
{
UINT rc;
MSIHANDLE view;
MSIHANDLE row = 0;
static const CHAR *Query="SELECT * from Icon";
MSIPACKAGE* package;
DWORD sz;
package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
if (!package)
return ERROR_INVALID_HANDLE;
rc = MsiDatabaseOpenViewA(package->db, Query, &view);
if (rc != ERROR_SUCCESS)
return rc;
rc = MsiViewExecute(view, 0);
if (rc != ERROR_SUCCESS)
{
MsiViewClose(view);
MsiCloseHandle(view);
return rc;
}
while (1)
{
HANDLE the_file;
WCHAR FilePath[MAX_PATH];
WCHAR FileName[MAX_PATH];
CHAR buffer[1024];
rc = MsiViewFetch(view,&row);
if (rc != ERROR_SUCCESS)
{
rc = ERROR_SUCCESS;
break;
}
sz = MAX_PATH;
MsiRecordGetStringW(row,1,FileName,&sz);
if (sz == 0)
{
ERR("Unable to get FileName\n");
MsiCloseHandle(row);
continue;
}
build_icon_path(hPackage,FileName,FilePath);
TRACE("Creating icon file at %s\n",debugstr_w(FilePath));
the_file = CreateFileW(FilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (the_file == INVALID_HANDLE_VALUE)
{
ERR("Unable to create file %s\n",debugstr_w(FilePath));
MsiCloseHandle(row);
continue;
}
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(FilePath);
break;
}
WriteFile(the_file,buffer,sz,&write,NULL);
} while (sz == 1024);
CloseHandle(the_file);
MsiCloseHandle(row);
}
MsiViewClose(view);
MsiCloseHandle(view);
return rc;
}
/* Msi functions that seem approperate here */
UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
{

View File

@ -173,27 +173,6 @@ static VOID set_installer_properties(MSIHANDLE hPackage)
static const WCHAR TF[]=
{'T','e','m','p','F','o','l','d','e','r',0};
/* Not yet set ... but needed by iTunes
*
DesktopFolder
FavoritesFolder
FontsFolder
PrimaryVolumePath
ProgramFiles64Folder
ProgramMenuFolder
SendToFolder
StartMenuFolder
StartupFolder
System16Folder
System64Folder
TemplateFolder
*/
/* asked for by iTunes ... but are they installer set?
*
* GlobalAssemblyCache
*/
/*
* Other things i notice set
*
@ -266,6 +245,7 @@ Privilaged
GetTempPathW(MAX_PATH,pth);
MsiSetPropertyW(hPackage, TF, pth);
/* in a wine enviroment the user is always admin and privlaged */
MsiSetPropertyA(hPackage,"AdminUser","1");
MsiSetPropertyA(hPackage,"Privileged","1");
@ -288,8 +268,26 @@ Privilaged
MsiSetPropertyA(hPackage,"WindowsBuild",verstr);
/* just fudge this */
MsiSetPropertyA(hPackage,"ServicePackLevel","6");
}
/* FIXME: these need to be set properly */
MsiSetPropertyA(hPackage,"ProgramMenuFolder",
"C:\\Windows\\Start Menu\\Programs\\");
MsiSetPropertyA(hPackage,"FavoritesFolder",
"C:\\Windows\\Favorites\\");
MsiSetPropertyA(hPackage,"FontsFolder",
"C:\\Windows\\Fonts\\");
MsiSetPropertyA(hPackage,"SendToFolder",
"C:\\Windows\\SendTo\\");
MsiSetPropertyA(hPackage,"StartMenuFolder",
"C:\\Windows\\Start Menu\\");
MsiSetPropertyA(hPackage,"StartupFolder",
"C:\\Windows\\Start Menu\\Programs\\Startup\\");
MsiSetPropertyA(hPackage,"TemplateFolder",
"C:\\Windows\\ShellNew\\");
MsiSetPropertyA(hPackage, "DesktopFolder",
"C:\\Windows\\Desktop\\");
}
UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
{