Implemented registering Classes and ProgID.

This commit is contained in:
Aric Stewart 2004-07-06 18:53:11 +00:00 committed by Alexandre Julliard
parent fcb20c53f7
commit 8f0a761948
1 changed files with 483 additions and 6 deletions

View File

@ -143,6 +143,8 @@ static UINT ACTION_InstallInitialize(MSIHANDLE hPackage);
static UINT ACTION_InstallValidate(MSIHANDLE hPackage);
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 HANDLE_CustomType1(MSIHANDLE hPackage, const LPWSTR source,
const LPWSTR target, const INT type);
@ -193,6 +195,10 @@ const static WCHAR szProcessComponents[] =
const static 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 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};
/********************************************************
* helper functions to get around current HACKS and such
@ -842,14 +848,16 @@ UINT ACTION_PerformAction(MSIHANDLE hPackage, const WCHAR *action)
rc = ACTION_WriteRegistryValues(hPackage);
else if (strcmpW(action,szRegisterTypeLibraries)==0)
rc = ACTION_RegisterTypeLibraries(hPackage);
else if (strcmpW(action,szRegisterClassInfo)==0)
rc = ACTION_RegisterClassInfo(hPackage);
else if (strcmpW(action,szRegisterProgIdInfo)==0)
rc = ACTION_RegisterProgIdInfo(hPackage);
/*
Current called during itunes but unimplemented and seem important
ResolveSource (sets SourceDir)
CreateShortcuts (would be nice to have soon)
RegisterClassInfo
RegisterProgIdInfo (Lots to do)
RegisterProduct
InstallFinalize
*/
@ -3245,6 +3253,473 @@ static UINT ACTION_RegisterTypeLibraries(MSIHANDLE hPackage)
}
static UINT register_appid(MSIHANDLE hPackage, LPCWSTR clsid, LPCWSTR app )
{
static const WCHAR szAppID[] = { 'A','p','p','I','D',0 };
UINT rc;
MSIHANDLE view;
MSIHANDLE row = 0;
static const WCHAR ExecSeqQuery[] =
{'S','E','L','E','C','T',' ','*',' ','f','r','o','m',' ','A','p','p','I'
,'d',' ','w','h','e','r','e',' ','A','p','p','I','d','=','`','%','s','`',0};
WCHAR Query[0x1000];
MSIPACKAGE* package;
HKEY hkey2,hkey3;
LPWSTR buffer=0;
DWORD sz;
package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
if (!package)
return ERROR_INVALID_HANDLE;
sprintfW(Query,ExecSeqQuery,clsid);
rc = MsiDatabaseOpenViewW(package->db, Query, &view);
if (rc != ERROR_SUCCESS)
return rc;
rc = MsiViewExecute(view, 0);
if (rc != ERROR_SUCCESS)
{
MsiViewClose(view);
MsiCloseHandle(view);
return rc;
}
RegCreateKeyW(HKEY_CLASSES_ROOT,szAppID,&hkey2);
RegCreateKeyW(hkey2,clsid,&hkey3);
RegSetValueExW(hkey3,NULL,0,REG_SZ,(LPVOID)app,
(strlenW(app)+1)*sizeof(WCHAR));
MsiViewFetch(view,&row);
if (!MsiRecordIsNull(row,2))
{
LPWSTR deformated=0;
UINT size;
static const WCHAR szRemoteServerName[] =
{'R','e','m','o','t','e','S','e','r','v','e','r','N','a','m','e',0};
sz = 0;
MsiRecordGetStringW(row,2,NULL,&sz);
sz++;
buffer = HeapAlloc(GetProcessHeap(),0,sz * sizeof (WCHAR));
MsiRecordGetStringW(row,2,buffer,&sz);
size = deformat_string(hPackage,buffer,&deformated);
RegSetValueExW(hkey3,szRemoteServerName,0,REG_SZ,(LPVOID)deformated,
size);
HeapFree(GetProcessHeap(),0,deformated);
HeapFree(GetProcessHeap(),0,buffer);
}
if (!MsiRecordIsNull(row,3))
{
static const WCHAR szLocalService[] =
{'L','o','c','a','l','S','e','r','v','i','c','e',0};
UINT size;
sz = 0;
MsiRecordGetStringW(row,3,NULL,&sz);
sz++;
size = sz * sizeof(WCHAR);
buffer = HeapAlloc(GetProcessHeap(),0,size);
MsiRecordGetStringW(row,3,buffer,&sz);
RegSetValueExW(hkey3,szLocalService,0,REG_SZ,(LPVOID)buffer,size);
HeapFree(GetProcessHeap(),0,buffer);
}
if (!MsiRecordIsNull(row,4))
{
static const WCHAR szService[] =
{'S','e','r','v','i','c','e','P','a','r','a','m','e','t','e','r','s',0};
UINT size;
sz = 0;
MsiRecordGetStringW(row,4,NULL,&sz);
sz++;
size = sz * sizeof(WCHAR);
buffer = HeapAlloc(GetProcessHeap(),0,size);
MsiRecordGetStringW(row,4,buffer,&sz);
RegSetValueExW(hkey3,szService,0,REG_SZ,(LPVOID)buffer,size);
HeapFree(GetProcessHeap(),0,buffer);
}
if (!MsiRecordIsNull(row,5))
{
static const WCHAR szDLL[] =
{'D','l','l','S','u','r','r','o','g','a','t','e',0};
UINT size;
sz = 0;
MsiRecordGetStringW(row,5,NULL,&sz);
sz++;
size = sz * sizeof(WCHAR);
buffer = HeapAlloc(GetProcessHeap(),0,size);
MsiRecordGetStringW(row,5,buffer,&sz);
RegSetValueExW(hkey3,szDLL,0,REG_SZ,(LPVOID)buffer,size);
HeapFree(GetProcessHeap(),0,buffer);
}
if (!MsiRecordIsNull(row,6))
{
static const WCHAR szActivate[] =
{'A','c','t','i','v','a','t','e','A','s','S','t','o','r','a','g','e',0};
static const WCHAR szY[] = {'Y',0};
if (MsiRecordGetInteger(row,6))
RegSetValueExW(hkey3,szActivate,0,REG_SZ,(LPVOID)szY,4);
}
if (!MsiRecordIsNull(row,7))
{
static const WCHAR szRunAs[] = {'R','u','n','A','s',0};
static const WCHAR szUser[] =
{'I','n','t','e','r','a','c','t','i','v','e',' ','U','s','e','r',0};
if (MsiRecordGetInteger(row,7))
RegSetValueExW(hkey3,szRunAs,0,REG_SZ,(LPVOID)szUser,34);
}
MsiCloseHandle(row);
MsiViewClose(view);
MsiCloseHandle(view);
RegCloseKey(hkey3);
RegCloseKey(hkey2);
return rc;
}
static UINT ACTION_RegisterClassInfo(MSIHANDLE hPackage)
{
/*
* again i am assuming the words, "Whose key file respesents" when refering
* to a Component as to meanin that Components KeyPath file
*
* Also there is a very strong connection between ClassInfo and ProgID
* that i am mostly glossing over.
* What would be more proper is to load the ClassInfo and the ProgID info
* into memory data structures and then be able to enable and disable them
* based on component.
*/
UINT rc;
MSIHANDLE view;
MSIHANDLE row = 0;
static const CHAR *ExecSeqQuery = "SELECT * from Class";
MSIPACKAGE* package;
static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 };
static const WCHAR szProgID[] = { 'P','r','o','g','I','D',0 };
static const WCHAR szAppID[] = { 'A','p','p','I','D',0 };
HKEY hkey,hkey2,hkey3;
package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
if (!package)
return ERROR_INVALID_HANDLE;
rc = RegCreateKeyW(HKEY_CLASSES_ROOT,szCLSID,&hkey);
if (rc != ERROR_SUCCESS)
return ERROR_FUNCTION_FAILED;
rc = MsiDatabaseOpenViewA(package->db, ExecSeqQuery, &view);
if (rc != ERROR_SUCCESS)
goto end;
rc = MsiViewExecute(view, 0);
if (rc != ERROR_SUCCESS)
{
MsiViewClose(view);
MsiCloseHandle(view);
goto end;
}
while (1)
{
WCHAR clsid[0x100];
WCHAR buffer[0x100];
WCHAR desc[0x100];
DWORD sz;
INT index;
rc = MsiViewFetch(view,&row);
if (rc != ERROR_SUCCESS)
{
rc = ERROR_SUCCESS;
break;
}
sz=0x100;
MsiRecordGetStringW(row,3,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 class reg due to disabled component\n");
MsiCloseHandle(row);
continue;
}
sz=0x100;
MsiRecordGetStringW(row,1,clsid,&sz);
RegCreateKeyW(hkey,clsid,&hkey2);
if (!MsiRecordIsNull(row,5))
{
sz=0x100;
MsiRecordGetStringW(row,5,desc,&sz);
RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)desc,
(strlenW(desc)+1)*sizeof(WCHAR));
}
else
desc[0]=0;
sz=0x100;
MsiRecordGetStringW(row,2,buffer,&sz);
RegCreateKeyW(hkey2,buffer,&hkey3);
index = get_loaded_file(package,package->components[index].KeyPath);
RegSetValueExW(hkey3,NULL,0,REG_SZ,
(LPVOID)package->files[index].TargetPath,
(strlenW(package->files[index].TargetPath)+1)
*sizeof(WCHAR));
RegCloseKey(hkey3);
if (!MsiRecordIsNull(row,4))
{
sz=0x100;
MsiRecordGetStringW(row,4,buffer,&sz);
RegCreateKeyW(hkey2,szProgID,&hkey3);
RegSetValueExW(hkey3,NULL,0,REG_SZ,(LPVOID)buffer,
(strlenW(buffer)+1)*sizeof(WCHAR));
RegCloseKey(hkey3);
}
if (!MsiRecordIsNull(row,6))
{
sz=0x100;
MsiRecordGetStringW(row,6,buffer,&sz);
RegSetValueExW(hkey2,szAppID,0,REG_SZ,(LPVOID)buffer,
(strlenW(buffer)+1)*sizeof(WCHAR));
register_appid(hPackage,buffer,desc);
}
RegCloseKey(hkey2);
FIXME("Process the rest of the fields >7\n");
ui_actiondata(hPackage,szRegisterClassInfo,row);
MsiCloseHandle(row);
}
MsiViewClose(view);
MsiCloseHandle(view);
end:
RegCloseKey(hkey);
return rc;
}
static UINT register_progid_base(MSIHANDLE row, LPWSTR clsid)
{
static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 };
HKEY hkey,hkey2;
WCHAR buffer[0x1000];
DWORD sz;
sz = 0x1000;
MsiRecordGetStringW(row,1,buffer,&sz);
RegCreateKeyW(HKEY_CLASSES_ROOT,buffer,&hkey);
if (!MsiRecordIsNull(row,4))
{
sz = 0x1000;
MsiRecordGetStringW(row,4,buffer,&sz);
RegSetValueExW(hkey,NULL,0,REG_SZ,(LPVOID)buffer, (strlenW(buffer)+1) *
sizeof(WCHAR));
}
if (!MsiRecordIsNull(row,3))
{
sz = 0x1000;
MsiRecordGetStringW(row,3,buffer,&sz);
RegCreateKeyW(hkey,szCLSID,&hkey2);
RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)buffer, (strlenW(buffer)+1) *
sizeof(WCHAR));
if (clsid)
strcpyW(clsid,buffer);
RegCloseKey(hkey2);
}
else
{
FIXME("UNHANDLED case, Parent progid but classid is NULL\n");
return ERROR_FUNCTION_FAILED;
}
if (!MsiRecordIsNull(row,5))
FIXME ("UNHANDLED icon in Progid\n");
return ERROR_SUCCESS;
}
static UINT register_progid(MSIHANDLE hPackage, MSIHANDLE row, LPWSTR clsid);
static UINT register_parent_progid(MSIHANDLE hPackage, LPCWSTR parent,
LPWSTR clsid)
{
UINT rc;
MSIHANDLE view;
MSIHANDLE row = 0;
static const WCHAR Query_t[] =
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','P','r','o','g'
,'I','d',' ','w','h','e','r','e',' ','P','r','o','g','I','d',' ','=',' ','`'
,'%','s','`',0};
WCHAR Query[0x1000];
MSIPACKAGE* package;
package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
if (!package)
return ERROR_INVALID_HANDLE;
sprintfW(Query,Query_t,parent);
rc = MsiDatabaseOpenViewW(package->db, 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;
}
register_progid(hPackage,row,clsid);
MsiCloseHandle(row);
MsiViewClose(view);
MsiCloseHandle(view);
return rc;
}
static UINT register_progid(MSIHANDLE hPackage, MSIHANDLE row, LPWSTR clsid)
{
UINT rc = ERROR_SUCCESS;
if (MsiRecordIsNull(row,2))
rc = register_progid_base(row,clsid);
else
{
WCHAR buffer[0x1000];
DWORD sz;
HKEY hkey,hkey2;
static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 };
sz = 0x1000;
MsiRecordGetStringW(row,2,buffer,&sz);
rc = register_parent_progid(hPackage,buffer,clsid);
sz = 0x1000;
MsiRecordGetStringW(row,1,buffer,&sz);
RegCreateKeyW(HKEY_CLASSES_ROOT,buffer,&hkey);
/* clasid is same as parent */
RegCreateKeyW(hkey,szCLSID,&hkey2);
RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)clsid, (strlenW(clsid)+1) *
sizeof(WCHAR));
RegCloseKey(hkey2);
if (!MsiRecordIsNull(row,4))
{
sz = 0x1000;
MsiRecordGetStringW(row,4,buffer,&sz);
RegSetValueExW(hkey,NULL,0,REG_SZ,(LPVOID)buffer,
(strlenW(buffer)+1) * sizeof(WCHAR));
}
if (!MsiRecordIsNull(row,5))
FIXME ("UNHANDLED icon in Progid\n");
RegCloseKey(hkey);
}
return rc;
}
static UINT ACTION_RegisterProgIdInfo(MSIHANDLE hPackage)
{
/*
* Sigh, here i am just brute force registering all progid
* this needs to be linked to the Classes that have been registerd
* but the easiest way to do that is to load all these stuff into
* memory for easy checking.
*
* gives me something to continue to work toward
*/
UINT rc;
MSIHANDLE view;
MSIHANDLE row = 0;
static const CHAR *Query = "SELECT * FROM ProgId";
MSIPACKAGE* package;
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)
{
WCHAR clsid[0x1000];
rc = MsiViewFetch(view,&row);
if (rc != ERROR_SUCCESS)
{
rc = ERROR_SUCCESS;
break;
}
register_progid(hPackage,row,clsid);
MsiCloseHandle(row);
}
MsiViewClose(view);
MsiCloseHandle(view);
return rc;
}
/* Msi functions that seem approperate here */
UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
{
@ -3488,11 +3963,13 @@ static UINT ACTION_Template(MSIHANDLE hPackage)
MSIHANDLE view;
MSIHANDLE row = 0;
static const CHAR *ExecSeqQuery;
MSIHANDLE db;
MSIPACKAGE* package;
db = MsiGetActiveDatabase(hPackage);
rc = MsiDatabaseOpenViewA(db, ExecSeqQuery, &view);
MsiCloseHandle(db);
package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
if (!package)
return ERROR_INVALID_HANDLE;
rc = MsiDatabaseOpenViewA(package->db, ExecSeqQuery, &view);
if (rc != ERROR_SUCCESS)
return rc;