shell32: Check for internal shell classes before querying the registry in SHCoCreateInstance.

This commit is contained in:
Alexandre Julliard 2007-10-18 15:15:40 +02:00
parent 9984ac8a12
commit d7892ccf2b
1 changed files with 19 additions and 33 deletions

View File

@ -128,10 +128,8 @@ HRESULT WINAPI SHCoCreateInstance(
const WCHAR sInProcServer32[16] ={'\\','I','n','p','r','o','c','S','e','r','v','e','r','3','2','\0'}; const WCHAR sInProcServer32[16] ={'\\','I','n','p','r','o','c','S','e','r','v','e','r','3','2','\0'};
const WCHAR sLoadWithoutCOM[15] ={'L','o','a','d','W','i','t','h','o','u','t','C','O','M','\0'}; const WCHAR sLoadWithoutCOM[15] ={'L','o','a','d','W','i','t','h','o','u','t','C','O','M','\0'};
WCHAR sDllPath[MAX_PATH]; WCHAR sDllPath[MAX_PATH];
HKEY hKey; HKEY hKey = 0;
DWORD dwSize; DWORD dwSize;
BOOLEAN bLoadFromShell32 = FALSE;
BOOLEAN bLoadWithoutCOM = FALSE;
IClassFactory * pcf = NULL; IClassFactory * pcf = NULL;
if(!ppv) return E_POINTER; if(!ppv) return E_POINTER;
@ -148,42 +146,33 @@ HRESULT WINAPI SHCoCreateInstance(
TRACE("(%p,%s,unk:%p,%s,%p)\n", TRACE("(%p,%s,unk:%p,%s,%p)\n",
aclsid,shdebugstr_guid(myclsid),pUnkOuter,shdebugstr_guid(refiid),ppv); aclsid,shdebugstr_guid(myclsid),pUnkOuter,shdebugstr_guid(refiid),ppv);
if (SUCCEEDED(DllGetClassObject(myclsid, &IID_IClassFactory,(LPVOID*)&pcf)))
{
hres = IClassFactory_CreateInstance(pcf, pUnkOuter, refiid, ppv);
IClassFactory_Release(pcf);
goto end;
}
/* we look up the dll path in the registry */ /* we look up the dll path in the registry */
__SHGUIDToStringW(myclsid, sClassID); __SHGUIDToStringW(myclsid, sClassID);
lstrcpyW(sKeyName, sCLSID); lstrcpyW(sKeyName, sCLSID);
lstrcatW(sKeyName, sClassID); lstrcatW(sKeyName, sClassID);
lstrcatW(sKeyName, sInProcServer32); lstrcatW(sKeyName, sInProcServer32);
if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_CLASSES_ROOT, sKeyName, 0, KEY_READ, &hKey)) { if (RegOpenKeyExW(HKEY_CLASSES_ROOT, sKeyName, 0, KEY_READ, &hKey))
dwSize = sizeof(sDllPath); return E_ACCESSDENIED;
SHQueryValueExW(hKey, NULL, 0,0, sDllPath, &dwSize );
/* if a special registry key is set, we load a shell extension without help of OLE32 */
bLoadWithoutCOM = (ERROR_SUCCESS == SHQueryValueExW(hKey, sLoadWithoutCOM, 0, 0, 0, 0));
/* if the com object is inside shell32, omit use of ole32 */
bLoadFromShell32 = (0==lstrcmpiW( PathFindFileNameW(sDllPath), sShell32));
RegCloseKey (hKey);
} else {
/* since we can't find it in the registry we try internally */
bLoadFromShell32 = TRUE;
}
TRACE("WithoutCom=%u FromShell=%u\n", bLoadWithoutCOM, bLoadFromShell32);
/* now we create an instance */
if (bLoadFromShell32) {
if (! SUCCEEDED(DllGetClassObject(myclsid, &IID_IClassFactory,(LPVOID*)&pcf))) {
ERR("LoadFromShell failed for CLSID=%s\n", shdebugstr_guid(myclsid));
}
} else if (bLoadWithoutCOM) {
/* if a special registry key is set, we load a shell extension without help of OLE32 */
if (!SHQueryValueExW(hKey, sLoadWithoutCOM, 0, 0, 0, 0))
{
/* load an external dll without ole32 */ /* load an external dll without ole32 */
HANDLE hLibrary; HANDLE hLibrary;
typedef HRESULT (CALLBACK *DllGetClassObjectFunc)(REFCLSID clsid, REFIID iid, LPVOID *ppv); typedef HRESULT (CALLBACK *DllGetClassObjectFunc)(REFCLSID clsid, REFIID iid, LPVOID *ppv);
DllGetClassObjectFunc DllGetClassObject; DllGetClassObjectFunc DllGetClassObject;
dwSize = sizeof(sDllPath);
SHQueryValueExW(hKey, NULL, 0,0, sDllPath, &dwSize );
if ((hLibrary = LoadLibraryExW(sDllPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH)) == 0) { if ((hLibrary = LoadLibraryExW(sDllPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH)) == 0) {
ERR("couldn't load InprocServer32 dll %s\n", debugstr_w(sDllPath)); ERR("couldn't load InprocServer32 dll %s\n", debugstr_w(sDllPath));
hres = E_ACCESSDENIED; hres = E_ACCESSDENIED;
@ -198,19 +187,16 @@ HRESULT WINAPI SHCoCreateInstance(
goto end; goto end;
} }
hres = IClassFactory_CreateInstance(pcf, pUnkOuter, refiid, ppv);
IClassFactory_Release(pcf);
} else { } else {
/* load an external dll in the usual way */ /* load an external dll in the usual way */
hres = CoCreateInstance(myclsid, pUnkOuter, CLSCTX_INPROC_SERVER, refiid, ppv); hres = CoCreateInstance(myclsid, pUnkOuter, CLSCTX_INPROC_SERVER, refiid, ppv);
goto end;
} }
/* here we should have a ClassFactory */
if (!pcf) return E_ACCESSDENIED;
hres = IClassFactory_CreateInstance(pcf, pUnkOuter, refiid, ppv);
IClassFactory_Release(pcf);
end: end:
if (hKey) RegCloseKey(hKey);
if(hres!=S_OK) if(hres!=S_OK)
{ {
ERR("failed (0x%08x) to create CLSID:%s IID:%s\n", ERR("failed (0x%08x) to create CLSID:%s IID:%s\n",