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_InstallValidate(MSIHANDLE hPackage);
static UINT ACTION_ProcessComponents(MSIHANDLE hPackage); static UINT ACTION_ProcessComponents(MSIHANDLE hPackage);
static UINT ACTION_RegisterTypeLibraries(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, static UINT HANDLE_CustomType1(MSIHANDLE hPackage, const LPWSTR source,
const LPWSTR target, const INT type); const LPWSTR target, const INT type);
@ -193,6 +195,10 @@ const static WCHAR szProcessComponents[] =
const static WCHAR szRegisterTypeLibraries[] = const static WCHAR szRegisterTypeLibraries[] =
{'R','e','g','i','s','t','e','r','T','y','p','e','L','i','b','r','a','r', {'R','e','g','i','s','t','e','r','T','y','p','e','L','i','b','r','a','r',
'i','e','s',0}; '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 * 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); rc = ACTION_WriteRegistryValues(hPackage);
else if (strcmpW(action,szRegisterTypeLibraries)==0) else if (strcmpW(action,szRegisterTypeLibraries)==0)
rc = ACTION_RegisterTypeLibraries(hPackage); 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 Current called during itunes but unimplemented and seem important
ResolveSource (sets SourceDir) ResolveSource (sets SourceDir)
CreateShortcuts (would be nice to have soon) CreateShortcuts (would be nice to have soon)
RegisterClassInfo
RegisterProgIdInfo (Lots to do)
RegisterProduct RegisterProduct
InstallFinalize 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 */ /* Msi functions that seem approperate here */
UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction ) UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
{ {
@ -3488,11 +3963,13 @@ static UINT ACTION_Template(MSIHANDLE hPackage)
MSIHANDLE view; MSIHANDLE view;
MSIHANDLE row = 0; MSIHANDLE row = 0;
static const CHAR *ExecSeqQuery; static const CHAR *ExecSeqQuery;
MSIHANDLE db; MSIPACKAGE* package;
db = MsiGetActiveDatabase(hPackage); package = msihandle2msiinfo(hPackage, MSIHANDLETYPE_PACKAGE);
rc = MsiDatabaseOpenViewA(db, ExecSeqQuery, &view); if (!package)
MsiCloseHandle(db); return ERROR_INVALID_HANDLE;
rc = MsiDatabaseOpenViewA(package->db, ExecSeqQuery, &view);
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
return rc; return rc;