890 lines
24 KiB
C++
890 lines
24 KiB
C++
/******************************************************************************
|
|
* Temp conversion utility to take registry entries and populate the class store with those entries.
|
|
*****************************************************************************/
|
|
|
|
/******************************************************************************
|
|
includes
|
|
******************************************************************************/
|
|
#include "precomp.hxx"
|
|
|
|
#include "..\appmgr\resource.h"
|
|
extern HINSTANCE ghInstance;
|
|
#define WTOA(sz, wsz, cch) WideCharToMultiByte(CP_ACP, 0, wsz, -1, sz, cch, NULL, NULL)
|
|
|
|
#define HOME 1
|
|
|
|
/******************************************************************************
|
|
defines and prototypes
|
|
******************************************************************************/
|
|
|
|
extern CLSID CLSID_ClassStore;
|
|
extern const IID IID_IClassAdmin;
|
|
|
|
CLSID CLSID_ClassStore = { /* 62392950-1AF8-11d0-B267-00A0C90F56FC */
|
|
0x62392950,
|
|
0x1af8,
|
|
0x11d0,
|
|
{0xb2, 0x67, 0x00, 0xa0, 0xc9, 0x0f, 0x56, 0xfc}
|
|
};
|
|
|
|
const IID IID_IClassStore = {
|
|
0x00000190,
|
|
0x0000,
|
|
0x0000,
|
|
{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}
|
|
};
|
|
|
|
const IID IID_IClassAdmin = {
|
|
0x00000191,
|
|
0x0000,
|
|
0x0000,
|
|
{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}
|
|
};
|
|
int
|
|
CompareClassDetails(
|
|
CLASSDETAIL * p1,
|
|
CLASSDETAIL * p2 );
|
|
|
|
HRESULT
|
|
UpdateDatabaseFromRegistry(
|
|
MESSAGE * pMessage );
|
|
|
|
HRESULT
|
|
UpdateClassStoreFromDatabase(
|
|
MESSAGE * pMessage,
|
|
IClassAdmin * pClassAdmin );
|
|
|
|
HRESULT
|
|
UpdateClassStoreFromMessage(
|
|
MESSAGE * pMessage,
|
|
IClassAdmin * pClassAdmin );
|
|
|
|
HRESULT
|
|
UpdateClassAssociations(
|
|
MESSAGE * pMessage,
|
|
IClassAdmin * pClassAdmin );
|
|
|
|
void
|
|
RemoveClassAssociations(
|
|
MESSAGE * pMessage,
|
|
IClassAdmin * pClassAdmin );
|
|
|
|
HRESULT
|
|
UpdatePackageDetails(
|
|
MESSAGE * pMessage,
|
|
IClassAdmin * pClassAdmin );
|
|
|
|
void
|
|
RemoveOneClassAssociation(
|
|
MESSAGE * pMessage,
|
|
CLASS_ENTRY * pClsEntry,
|
|
IClassAdmin * pClassAdmin );
|
|
|
|
HRESULT
|
|
UpdateOneClassAssociation(
|
|
MESSAGE * pMessage,
|
|
CLASS_ENTRY * pClsEntry,
|
|
IClassAdmin * pClassAdmin );
|
|
|
|
HRESULT
|
|
UpdateOnePackageDetail(
|
|
MESSAGE * pMessage,
|
|
PACKAGE_ENTRY * pClsEntry,
|
|
IClassAdmin * pClassAdmin );
|
|
|
|
LONG
|
|
UpdateDatabaseFromTypelib(
|
|
MESSAGE * pMessage );
|
|
|
|
void
|
|
DumpTypelibEntries(
|
|
MESSAGE * pMessage );
|
|
|
|
|
|
LONG
|
|
UpdateDatabaseFromFileExt(
|
|
MESSAGE * pMessage );
|
|
LONG
|
|
UpdateDatabaseFromProgID(
|
|
MESSAGE * pMessage );
|
|
|
|
LONG
|
|
UpdateDatabaseFromIID(
|
|
MESSAGE * pMessage );
|
|
|
|
|
|
HRESULT
|
|
AddToClassStore(
|
|
MESSAGE *pMessage,
|
|
IClassAdmin * pClassAdmin );
|
|
|
|
void
|
|
AppEntryToAppDetail(
|
|
APP_ENTRY * pAppEntry,
|
|
APPDETAIL * pAppDetail );
|
|
|
|
HRESULT
|
|
UpdatePackageDetails(
|
|
MESSAGE * pMessage,
|
|
IClassAdmin * pClassAdmin );
|
|
|
|
void
|
|
AppEntryToAppDetail(
|
|
APP_ENTRY * pAppEntry,
|
|
APPDETAIL * pAppDetail );
|
|
|
|
HRESULT
|
|
UpdateInterfaceEntries(
|
|
MESSAGE * pMessage,
|
|
IClassAdmin * pClassAdmin );
|
|
|
|
HRESULT
|
|
UpdateOneInterfaceEntry(
|
|
MESSAGE * pMessage,
|
|
ITF_ENTRY * pITFEntry,
|
|
IClassAdmin * pClassAdmin );
|
|
|
|
/******************************************************************************
|
|
Da Code
|
|
******************************************************************************/
|
|
|
|
HRESULT
|
|
VerifyArguments( MESSAGE * pMessage )
|
|
{
|
|
// if( !pMessage->pRegistryKeyName )
|
|
// return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_INVALID_PARAMETER );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
UpdateDatabaseFromRegistry(
|
|
MESSAGE * pMessage )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
hr = HRESULT_FROM_WIN32( UpdateDatabaseFromCLSID( pMessage ));
|
|
|
|
if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr )
|
|
return UpdateDatabaseFromFileExt(pMessage);
|
|
|
|
if ( !SUCCEEDED(hr ) )
|
|
return hr;
|
|
|
|
hr = HRESULT_FROM_WIN32( UpdateDatabaseFromFileExt( pMessage ));
|
|
|
|
if ( !SUCCEEDED(hr ) )
|
|
return hr;
|
|
|
|
hr = HRESULT_FROM_WIN32( UpdateDatabaseFromProgID( pMessage ));
|
|
|
|
if ( !SUCCEEDED(hr ) )
|
|
return hr;
|
|
|
|
hr = HRESULT_FROM_WIN32( UpdateDatabaseFromIID( pMessage ));
|
|
|
|
if ( !SUCCEEDED(hr ) )
|
|
return hr;
|
|
|
|
hr = HRESULT_FROM_WIN32( UpdateDatabaseFromTypelib( pMessage ));
|
|
|
|
if ( !SUCCEEDED(hr ) )
|
|
return hr;
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
UpdateClassStoreFromDatabase( MESSAGE * pMessage, IClassAdmin * pClassAdmin )
|
|
{
|
|
HRESULT hr;
|
|
|
|
|
|
hr = UpdateClassAssociations( pMessage, pClassAdmin );
|
|
|
|
if ( SUCCEEDED(hr))
|
|
{
|
|
hr = UpdateInterfaceEntries( pMessage, pClassAdmin );
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
hr = UpdatePackageDetails( pMessage, pClassAdmin );
|
|
}
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
// We blew it somewhere so we need to remove all the CLSIDs that we
|
|
// might have added.
|
|
RemoveClassAssociations( pMessage, pClassAdmin);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
UpdateClassStoreFromMessage( MESSAGE * pMessage, IClassAdmin * pClassAdmin )
|
|
{
|
|
HRESULT hr;
|
|
|
|
if ( (hr = VerifyArguments( pMessage )) == S_OK )
|
|
{
|
|
hr = UpdateDatabaseFromRegistry( pMessage );
|
|
if (SUCCEEDED(hr) || MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32,ERROR_NO_MORE_ITEMS) == hr)
|
|
{
|
|
if (pMessage->hRoot != HKEY_CLASSES_ROOT)
|
|
{
|
|
// We mapped it into a temporary key so we need to do a pass
|
|
// on HKEY_CLASSES_ROOT as well in order to catch anything
|
|
// that might have been copied there instead of into our
|
|
// remapped key.
|
|
// This is a problem because we can't remap HKCR across
|
|
// process boundaries, our remapping function only works in
|
|
// this process.
|
|
pMessage->hRoot = HKEY_CLASSES_ROOT;
|
|
hr = UpdateDatabaseFromRegistry( pMessage );
|
|
}
|
|
if (SUCCEEDED(hr) || MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32,ERROR_NO_MORE_ITEMS) == hr)
|
|
{
|
|
hr = UpdateClassStoreFromDatabase( pMessage, pClassAdmin );
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
|
|
}
|
|
|
|
HRESULT
|
|
UpdateInterfaceEntries(
|
|
MESSAGE * pMessage,
|
|
IClassAdmin * pClassAdmin )
|
|
{
|
|
ITF_ENTRY * pITFEntry = (ITF_ENTRY *)pMessage->pIIDict->GetFirst();
|
|
HRESULT hr;
|
|
|
|
if ( pITFEntry )
|
|
{
|
|
do
|
|
{
|
|
hr = UpdateOneInterfaceEntry(pMessage,pITFEntry,pClassAdmin);
|
|
if ( !SUCCEEDED(hr) )
|
|
return hr;
|
|
pITFEntry = pMessage->pIIDict->GetNext( pITFEntry );
|
|
} while ( pITFEntry != 0 );
|
|
}
|
|
else
|
|
hr = MAKE_HRESULT( SEVERITY_SUCCESS, 0, 1 ); // no interfaces.
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
UpdateOneInterfaceEntry(
|
|
MESSAGE * pMessage,
|
|
ITF_ENTRY * pITFEntry,
|
|
IClassAdmin * pClassAdmin )
|
|
{
|
|
CLSID IID;
|
|
CLSID PSClsid;
|
|
CLSID TypelibID;
|
|
|
|
StringToCLSID( &pITFEntry->IID[1], &IID );
|
|
StringToCLSID( &pITFEntry->Clsid[1], &PSClsid );
|
|
StringToCLSID( &pITFEntry->TypelibID[1], &PSClsid );
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if ( !pMessage->fDumpOnly )
|
|
hr = pClassAdmin->NewInterface( IID, L"", PSClsid, TypelibID );
|
|
|
|
if (hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS))
|
|
hr = S_OK;
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
UpdatePackageDetails(
|
|
MESSAGE * pMessage,
|
|
IClassAdmin * pClassAdmin )
|
|
{
|
|
PACKAGE_ENTRY * pPackageEntry =
|
|
(PACKAGE_ENTRY *)pMessage->pPackageDict->GetFirst();
|
|
HRESULT hr = S_OK;
|
|
hr = E_FAIL;
|
|
|
|
if ( pPackageEntry )
|
|
{
|
|
do
|
|
{
|
|
hr = UpdateOnePackageDetail(pMessage,pPackageEntry,pClassAdmin);
|
|
if (!SUCCEEDED(hr))
|
|
return hr;
|
|
pPackageEntry = pMessage->pPackageDict->GetNext(pPackageEntry);
|
|
} while ( pPackageEntry != 0 );
|
|
}
|
|
else
|
|
hr = MAKE_HRESULT( SEVERITY_SUCCESS, 0, 1 ); // no packages.
|
|
return hr;
|
|
|
|
}
|
|
|
|
HRESULT
|
|
UpdateOnePackageDetail(
|
|
MESSAGE * pMessage,
|
|
PACKAGE_ENTRY * pPackageEntry,
|
|
IClassAdmin * pClassAdmin )
|
|
{
|
|
PACKAGEDETAIL PackageDetail;
|
|
APP_ENTRY *pAppEntry;
|
|
int len;
|
|
int count;
|
|
HRESULT hr = S_OK;
|
|
int Index = 0;
|
|
int max;
|
|
|
|
// copy the bare package details
|
|
|
|
memcpy( &PackageDetail,
|
|
&pPackageEntry->PackageDetails,
|
|
sizeof( PACKAGEDETAIL ) );
|
|
|
|
count = PackageDetail.cApps = pPackageEntry->Count;
|
|
|
|
// if the null appid contains at least one clsid entry or typelib entry
|
|
// assume one more app id in the package. There can be either a clsid entry or
|
|
// a typelib entry in the null appid.
|
|
|
|
if ( (pPackageEntry->GetCountOfClsidsInNullAppid() > 0 ) ||
|
|
(pPackageEntry->GetCountOfTypelibsInNullAppid() > 0 )
|
|
)
|
|
{
|
|
PackageDetail.cApps += 1;
|
|
count++;
|
|
}
|
|
|
|
|
|
// Allocate an APPDETAIL structure if there is at least one appid in the
|
|
// package.
|
|
|
|
if ( count )
|
|
{
|
|
PackageDetail.pAppDetail = new APPDETAIL[ count ];
|
|
memset( PackageDetail.pAppDetail, '\0', count * sizeof(APPDETAIL) );
|
|
}
|
|
|
|
// update the rest of entries that have an appid.
|
|
|
|
for ( Index = 0, pAppEntry = pPackageEntry->pAppDict->GetFirst();
|
|
pAppEntry && (Index < pPackageEntry->Count);
|
|
++Index, pAppEntry = pPackageEntry->pAppDict->GetNext( pAppEntry) )
|
|
{
|
|
AppEntryToAppDetail(pAppEntry, &PackageDetail.pAppDetail[ Index ] );
|
|
}
|
|
|
|
//
|
|
// If there is at least one clsid in the null appid, then assign the appid
|
|
// the same guid as the first clsid in the list. Else, if there is at least
|
|
// one typelib in the list, assign the appid the same guid as the typelib id
|
|
//
|
|
|
|
|
|
if ( (max = pPackageEntry->GetCountOfClsidsInNullAppid()) > 0 )
|
|
{
|
|
APP_ENTRY A;
|
|
char * p = pPackageEntry->GetFirstClsidInNullAppidList();
|
|
|
|
A.SetAppIDString( p );
|
|
|
|
|
|
// Add the Class ids from the NUll app entry list to the app entry..
|
|
|
|
for ( count = 0, p = pPackageEntry->ClsidsInNullAppid->GetFirst();
|
|
p && (count < max);
|
|
++count, p = pPackageEntry->ClsidsInNullAppid->GetNext( p )
|
|
)
|
|
{
|
|
A.AddClsid( p );
|
|
}
|
|
|
|
|
|
// update the entries with the null clsid.
|
|
|
|
AppEntryToAppDetail( &A, &PackageDetail.pAppDetail [ Index ] );
|
|
|
|
// Add remote server names to app entry ( not implemented yet ).
|
|
|
|
}
|
|
else if ( (max = pPackageEntry->GetCountOfTypelibsInNullAppid()) > 0 )
|
|
{
|
|
APP_ENTRY A;
|
|
char * p = pPackageEntry->GetFirstTypelibInNullAppidList();
|
|
|
|
A.SetAppIDString( p );
|
|
|
|
|
|
// Add the Class ids from the NUll app entry list to the app entry..
|
|
|
|
for ( count = 0, p = pPackageEntry->TypelibsInNullAppid->GetFirst();
|
|
p && (count < max);
|
|
++count, p = pPackageEntry->TypelibsInNullAppid->GetNext( p )
|
|
)
|
|
{
|
|
A.AddTypelib( p );
|
|
}
|
|
|
|
|
|
// update the entries with the null clsid.
|
|
|
|
AppEntryToAppDetail( &A, &PackageDetail.pAppDetail [ Index ] );
|
|
|
|
}
|
|
|
|
// update package name.
|
|
|
|
len = strlen( &pPackageEntry->PackageName[0] );
|
|
PackageDetail.pszPackageName = new OLECHAR[ (len +1 )*2 ];
|
|
mbstowcs(PackageDetail.pszPackageName,&pPackageEntry->PackageName[0],len+1);
|
|
|
|
// write the class store.
|
|
|
|
|
|
if ( pMessage->fDumpOnly)
|
|
{
|
|
(*pMessage->pDumpOnePackage)( pMessage, &PackageDetail );
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
hr = pClassAdmin->NewPackage( &PackageDetail );
|
|
|
|
return hr;
|
|
}
|
|
|
|
void
|
|
RemoveClassAssociations(
|
|
MESSAGE * pMessage,
|
|
IClassAdmin * pClassAdmin )
|
|
{
|
|
CLASS_ENTRY * pClsEntry = pMessage->pClsDict->GetFirst();
|
|
|
|
if ( pClsEntry )
|
|
{
|
|
do
|
|
{
|
|
RemoveOneClassAssociation( pMessage, pClsEntry, pClassAdmin );
|
|
pClsEntry = pMessage->pClsDict->GetNext( pClsEntry );
|
|
} while ( pClsEntry != 0 );
|
|
}
|
|
}
|
|
|
|
void
|
|
RemoveOneClassAssociation(
|
|
MESSAGE * pMessage,
|
|
CLASS_ENTRY * pClsEntry,
|
|
IClassAdmin * pClassAdmin )
|
|
{
|
|
CLSID clsid;
|
|
StringToCLSID(&(pClsEntry->GetClsidString())[1], &clsid );
|
|
pClassAdmin->DeleteClass( clsid );
|
|
}
|
|
|
|
HRESULT
|
|
UpdateClassAssociations(
|
|
MESSAGE * pMessage,
|
|
IClassAdmin * pClassAdmin )
|
|
{
|
|
CLASS_ENTRY * pClsEntry = pMessage->pClsDict->GetFirst();
|
|
HRESULT hr = S_OK;
|
|
|
|
if ( pClsEntry )
|
|
{
|
|
do
|
|
{
|
|
hr = UpdateOneClassAssociation( pMessage, pClsEntry, pClassAdmin );
|
|
if (hr != S_OK )
|
|
return hr;
|
|
pClsEntry = pMessage->pClsDict->GetNext( pClsEntry );
|
|
} while ( pClsEntry != 0 );
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
UpdateOneClassAssociation(
|
|
MESSAGE * pMessage,
|
|
CLASS_ENTRY * pClsEntry,
|
|
IClassAdmin * pClassAdmin )
|
|
{
|
|
CLASSASSOCIATION CA;
|
|
LPOLESTR * prgFileExt;
|
|
LPOLESTR * prgProgID;
|
|
char * p;
|
|
int len;
|
|
ListEntry * pListEntry;
|
|
HRESULT hr = S_OK;
|
|
|
|
memcpy( &CA, &pClsEntry->ClassAssociation, sizeof( CLASSASSOCIATION ) );
|
|
|
|
CA.cFileExt = pClsEntry->FileExtList.GetCount();
|
|
CA.cOtherProgId = pClsEntry->OtherProgIDs.GetCount();
|
|
|
|
|
|
// convert the classid into a guid
|
|
|
|
StringToCLSID(&(pClsEntry->GetClsidString())[1], &CA.Clsid );
|
|
|
|
// create the file extension array.
|
|
|
|
if ( CA.cFileExt )
|
|
{
|
|
int count;
|
|
|
|
// allocate array for the file extensions.
|
|
|
|
CA.prgFileExt = prgFileExt = new LPOLESTR[ CA.cFileExt ];
|
|
|
|
// copy the file extensions one by one.
|
|
|
|
for ( count = 0, pListEntry = pClsEntry->FileExtList.GetFirst();
|
|
pListEntry;
|
|
++count, pListEntry = pClsEntry->FileExtList.GetNext( pListEntry )
|
|
)
|
|
{
|
|
char * p = (char *) pListEntry->pElement;
|
|
|
|
int len = strlen(p);
|
|
prgFileExt[ count ] = new OLECHAR[ (len+1)*2 ];
|
|
mbstowcs( prgFileExt[ count ], p, len+1 );
|
|
}
|
|
}
|
|
|
|
// create the progid array
|
|
if ( CA.cOtherProgId )
|
|
{
|
|
int count;
|
|
ListEntry * pListEntry;
|
|
|
|
// allocate array for the file extensions.
|
|
|
|
CA.prgOtherProgId = prgProgID = new LPOLESTR[ CA.cOtherProgId ];
|
|
|
|
// copy the file extensions one by one.
|
|
|
|
for ( count = 0, pListEntry = pClsEntry->OtherProgIDs.GetFirst();
|
|
pListEntry;
|
|
++count, pListEntry = pClsEntry->OtherProgIDs.GetNext( pListEntry )
|
|
)
|
|
{
|
|
p = (char *) pListEntry->pElement;
|
|
len = strlen(p);
|
|
|
|
prgProgID[ count ] = new OLECHAR[ (len +1) *2 ];
|
|
mbstowcs( prgProgID[ count ], p, len+1 );
|
|
}
|
|
}
|
|
|
|
// create the default progid - the first in the progidlist.
|
|
|
|
if ( pClsEntry->OtherProgIDs.GetCount() )
|
|
{
|
|
pListEntry = pClsEntry->OtherProgIDs.GetFirst();
|
|
p = (char *)pListEntry->pElement;
|
|
len = strlen(p);
|
|
CA.pDefaultProgId = new OLECHAR[ (len+1) * 2 ];
|
|
mbstowcs( CA.pDefaultProgId, p, len+1 );
|
|
}
|
|
else
|
|
CA.pDefaultProgId = 0;
|
|
|
|
if (CA.pszDesc == NULL)
|
|
{
|
|
CA.pszDesc = L"";
|
|
}
|
|
|
|
if ( !pMessage->fDumpOnly )
|
|
{
|
|
// First try and delete the class entry to make sure this class ID
|
|
// isn't orphaned from some earlier partial installation. If the
|
|
// classid is in the class store but isn't listed as being
|
|
// implemented by an application then this will cause it to be
|
|
// deleted. If it _IS_ implemented by another application then this
|
|
// wil be a NOP.
|
|
pClassAdmin->DeleteClass(CA.Clsid);
|
|
|
|
hr = pClassAdmin->NewClass( &CA );
|
|
}
|
|
|
|
if ( hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) ) // duplicate
|
|
{
|
|
// Get details of the pre-existing class.
|
|
CLASSDETAIL cdOld;
|
|
hr = pClassAdmin->GetClassDetails(CA.Clsid, &cdOld);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Check to see if they are equivalent (CompareClassDetails).
|
|
int i = CompareClassDetails(&CA, &cdOld);
|
|
|
|
if (0 != i)
|
|
{
|
|
// Inform the user of a conflict and abort
|
|
TCHAR szCaption[256];
|
|
TCHAR szBuffer[1024];
|
|
::LoadString(ghInstance, IDS_CLSIDCONFLICT1, szBuffer, 1024);
|
|
// UNDONE - we need to get the other application's name here.
|
|
strcpy(szCaption, "some other application");
|
|
IEnumPackage * pIEP;
|
|
CSPLATFORM cp;
|
|
memset(&cp, 0, sizeof(cp));
|
|
hr = pClassAdmin->GetPackagesEnum(CA.Clsid,
|
|
NULL,
|
|
cp,
|
|
0,
|
|
0,
|
|
&pIEP);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ULONG ul;
|
|
PACKAGEDETAIL pd;
|
|
hr = pIEP->Next(1, &pd, &ul);
|
|
if (SUCCEEDED(hr) && 1 == ul)
|
|
{
|
|
WTOA(szCaption, pd.pszPackageName, 256);
|
|
}
|
|
pIEP->Release();
|
|
}
|
|
strcat(szBuffer, szCaption);
|
|
::LoadString(ghInstance, IDS_CLSIDCONFLICT2, szCaption, 256);
|
|
strcat (szBuffer, szCaption);
|
|
strncpy(szCaption, pMessage->pPackagePath, 256);
|
|
int iReturn = ::MessageBox(pMessage->hwnd, szBuffer,
|
|
szCaption,
|
|
MB_OK);
|
|
hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS);
|
|
}
|
|
else
|
|
{
|
|
// they aren't different so it's OK to continue
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// before return, update the class association data structure back to the class
|
|
// entry structure, so that the dumper can use it.
|
|
|
|
memcpy( &pClsEntry->ClassAssociation, &CA, sizeof( CLASSASSOCIATION ) );
|
|
return hr;
|
|
}
|
|
|
|
// compares two class details
|
|
//
|
|
|
|
//
|
|
// Input: p1: Pointer to a CLASSDETAIL structure
|
|
// p2: Pointer to the other CLASSDETAIL structure
|
|
// Returns:
|
|
// 0 if all is well, -1 otherwise.
|
|
// Notes: DOES NOT CHECK FOR NULL INPUT POINTERS.
|
|
//
|
|
|
|
|
|
int
|
|
CompareClassDetails(
|
|
CLASSDETAIL * p1,
|
|
CLASSDETAIL * p2 )
|
|
{
|
|
|
|
// compare the class id.
|
|
|
|
if( _memicmp( (const void * )&p1->Clsid,
|
|
(const void *)&p2->Clsid,
|
|
sizeof( CLSID ) ) )
|
|
return -1;
|
|
|
|
// We do not compare pszdesc, since it is just an info field.
|
|
|
|
// We DO compare the icon paths, since if icon paths are different, they are
|
|
// likely to be different packages supporting the same classid. (I am not
|
|
// sure, this is a good argument)
|
|
|
|
if( p1->pszIconPath && p2->pszIconPath )
|
|
{
|
|
if( _wcsicmp( (const wchar_t *)p1->pszIconPath,
|
|
(const wchar_t *)p2->pszIconPath ) != 0 )
|
|
return -1;
|
|
}
|
|
|
|
// test the Treatas and AutoConvert CLSIDs
|
|
|
|
if( _memicmp( (const unsigned char *)&p1->TreatAsClsid,
|
|
(const unsigned char *)&p2->TreatAsClsid,
|
|
sizeof( CLSID ) ) )
|
|
return -1;
|
|
|
|
if( _memicmp( (const unsigned char *)&p1->AutoConvertClsid,
|
|
(const unsigned char *)&p2->AutoConvertClsid,
|
|
sizeof( CLSID ) ) )
|
|
return -1;
|
|
|
|
// If the count of file extensions do not match, they are likely different
|
|
// packages.
|
|
|
|
if( p1->cFileExt != p2->cFileExt )
|
|
return -1;
|
|
else
|
|
{
|
|
int i, cFileExt;
|
|
|
|
|
|
// All the file extensions should match for the guaranteeing that the
|
|
// package is the same.
|
|
|
|
for( i = 0, cFileExt = p1->cFileExt;
|
|
i < cFileExt;
|
|
++i
|
|
)
|
|
{
|
|
if(_wcsicmp( (const wchar_t *)p1->prgFileExt[ i ],
|
|
(const wchar_t *)p2->prgFileExt[ i ] ) != 0 )
|
|
return -1;
|
|
}
|
|
|
|
if( i < cFileExt )
|
|
return -1;
|
|
|
|
}
|
|
|
|
// compare mime type.
|
|
|
|
if( p1->pMimeType && p2->pMimeType )
|
|
{
|
|
if( _wcsicmp( (const wchar_t *)p1->pMimeType,
|
|
(const wchar_t *)p2->pMimeType ) != 0 )
|
|
return -1;
|
|
}
|
|
|
|
// compare default progid.
|
|
|
|
if( p1->pDefaultProgId && p2->pDefaultProgId )
|
|
{
|
|
if( _wcsicmp( (const wchar_t *)p1->pDefaultProgId,
|
|
(const wchar_t *)p2->pDefaultProgId ) != 0 )
|
|
return -1;
|
|
}
|
|
|
|
// if the count of Other prog ids do not match , they are likely different
|
|
// packages
|
|
|
|
if( p1->cOtherProgId != p2->cOtherProgId )
|
|
return -1;
|
|
else
|
|
{
|
|
int i, cOtherProgId;
|
|
|
|
|
|
// All the OtherProgIds should match for the guaranteeing that the
|
|
// package is the same.
|
|
|
|
for( i = 0, cOtherProgId = p1->cOtherProgId;
|
|
i < cOtherProgId;
|
|
++i
|
|
)
|
|
{
|
|
if(_wcsicmp((const wchar_t *)p1->prgOtherProgId[ i ],
|
|
(const wchar_t *)p2->prgOtherProgId[ i ]) != 0 )
|
|
return -1;
|
|
}
|
|
|
|
if( i < cOtherProgId )
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
AppEntryToAppDetail(
|
|
APP_ENTRY * pAppEntry,
|
|
APPDETAIL * pAppDetail )
|
|
{
|
|
int count;
|
|
ListEntry * pListEntry;
|
|
char * p;
|
|
|
|
StringToCLSID( &pAppEntry->AppIDString[1], &pAppDetail->AppID );
|
|
|
|
// pick up the clsid list.
|
|
|
|
if ( count = pAppEntry->ClsidList.GetCount() )
|
|
{
|
|
|
|
// Allocate space for requisite # of CLSIDs
|
|
|
|
pAppDetail->cClasses = count;
|
|
pAppDetail->prgClsIdList = new CLSID[ count ];
|
|
|
|
for ( count = 0, pListEntry = pAppEntry->ClsidList.GetFirst();
|
|
pListEntry;
|
|
pListEntry = pAppEntry->ClsidList.GetNext( pListEntry ), ++count
|
|
)
|
|
{
|
|
p = (char*)pListEntry->pElement;
|
|
StringToCLSID( p+1, &pAppDetail->prgClsIdList[count] );
|
|
}
|
|
}
|
|
|
|
// pick up typelib list.
|
|
|
|
if ( count = pAppEntry->TypelibList.GetCount() )
|
|
{
|
|
|
|
// Allocate space for requisite # of Typelibs
|
|
|
|
pAppDetail->cTypeLibIds = count;
|
|
pAppDetail->prgTypeLibIdList = new CLSID[ count ];
|
|
|
|
for ( count = 0, pListEntry = pAppEntry->TypelibList.GetFirst();
|
|
pListEntry;
|
|
pListEntry = pAppEntry->TypelibList.GetNext( pListEntry ), ++count
|
|
)
|
|
{
|
|
p = (char*)pListEntry->pElement;
|
|
StringToCLSID( p+1, &pAppDetail->prgTypeLibIdList[count] );
|
|
}
|
|
}
|
|
|
|
// pick up remote server name list.
|
|
|
|
if ( count = pAppEntry->RemoteServerNameList.GetCount() )
|
|
{
|
|
pAppDetail->prgServerNames = new LPOLESTR[ count ];
|
|
pAppDetail->cServers = count;
|
|
|
|
for ( count = 0, pListEntry = pAppEntry->RemoteServerNameList.GetFirst();
|
|
pListEntry;
|
|
pListEntry = pAppEntry->RemoteServerNameList.GetNext( pListEntry ), ++count
|
|
)
|
|
{
|
|
p = (char *) pListEntry->pElement;
|
|
int len = strlen(p);
|
|
|
|
pAppDetail->prgServerNames[ count ] = new OLECHAR[ (len +1) * 2 ];
|
|
mbstowcs( pAppDetail->prgServerNames[count], p, len+1 );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
HRESULT
|
|
AddToClassStore( MESSAGE *pMessage, IClassAdmin * pClassAdmin )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|