BOOL installIA2Support() { LPFNGETCLASSOBJECT IA2Dll_DllGetClassObject; int i; int res; if(isIA2Installed) return TRUE; if((IA2DllHandle=CoLoadLibrary(IA2DllPath,FALSE))==NULL) { LOG_ERROR(L"CoLoadLibrary failed"); return FALSE; } IA2Dll_DllGetClassObject=(LPFNGETCLASSOBJECT)GetProcAddress(static_cast<HMODULE>(IA2DllHandle),"DllGetClassObject"); assert(IA2Dll_DllGetClassObject); //IAccessible2 proxy dll must have this function IUnknown* ia2ClassObjPunk=NULL; if((res=IA2Dll_DllGetClassObject(IAccessible2ProxyIID,IID_IUnknown,(LPVOID*)&ia2ClassObjPunk))!=S_OK) { LOG_ERROR(L"Error calling DllGetClassObject, code "<<res); CoFreeLibrary(IA2DllHandle); IA2DllHandle=0; return FALSE; } if((res=CoRegisterClassObject(IAccessible2ProxyIID,ia2ClassObjPunk,CLSCTX_INPROC_SERVER,REGCLS_MULTIPLEUSE,(LPDWORD)&IA2RegCooky))!=S_OK) { LOG_DEBUGWARNING(L"Error registering class object, code "<<res); ia2ClassObjPunk->Release(); CoFreeLibrary(IA2DllHandle); IA2DllHandle=0; return FALSE; } ia2ClassObjPunk->Release(); for(i=0;i<ARRAYSIZE(ia2Iids);++i) { CoGetPSClsid(ia2Iids[i],&(_ia2PSClsidBackups[i])); CoRegisterPSClsid(ia2Iids[i],IAccessible2ProxyIID); } isIA2Installed=TRUE; return TRUE; }
MiniPlayer::~MiniPlayer(void) { _itLibs = _loadedLibs.begin(); for(; _itLibs != _loadedLibs.end(); ++_itLibs) { if(_itLibs->second) CoFreeLibrary(_itLibs->second); } _loadedLibs.clear(); CoUninitialize(); }
BOOL uninstallIA2Support() { int i; LPFNDLLCANUNLOADNOW IA2Dll_DllCanUnloadNow; if(isIA2Installed) { for(i=0;i<ARRAYSIZE(ia2Iids);++i) { CoRegisterPSClsid(ia2Iids[i],_ia2PSClsidBackups[i]); } CoRevokeClassObject(IA2RegCooky); IA2Dll_DllCanUnloadNow=(LPFNDLLCANUNLOADNOW)GetProcAddress(static_cast<HMODULE>(IA2DllHandle),"DllCanUnloadNow"); assert(IA2Dll_DllCanUnloadNow); //IAccessible2 proxy dll must have this function if(IA2Dll_DllCanUnloadNow()==S_OK) { CoFreeLibrary(IA2DllHandle); } IA2DllHandle=0; isIA2Installed=FALSE; } return TRUE; }
HRESULT MiniPlayer::CoCreateInstanceAx(LPCTSTR ax, REFCLSID rclsid, IUnknown *punkOuter, REFIID riid, LPVOID *ppv) { HINSTANCE hInst = _loadedLibs[ax]; if(hInst == NULL) hInst = CoLoadLibrary(const_cast<LPOLESTR>(ax), 0); if(!hInst) return -1; _loadedLibs[ax] = hInst; LPFNGETCLASSOBJECT pfnDllGetObjectClass = reinterpret_cast<LPFNGETCLASSOBJECT>(GetProcAddress(hInst, "DllGetClassObject")); if(!pfnDllGetObjectClass) return -1; IClassFactory *pClsFactory = NULL; HRESULT hr = pfnDllGetObjectClass(rclsid, IID_IClassFactory, (void **)&pClsFactory); IF_CHK(hr, "Unable to get Class Factory."); return pClsFactory->CreateInstance(punkOuter, riid, ppv); Cleanup: if(hInst) CoFreeLibrary(hInst); return hr; }
bool PluginLoader::RegisterShellExtDll(QString dllPath, bool bRegister,bool quiet) { if(Debug) { QString message; if(bRegister) message+=QString("Try load the dll: %1, and ").arg(dllPath); else message+=QString("Try unload the dll: %1, and ").arg(dllPath); if(quiet) message+=QString("don't open the UAC"); else message+=QString("open the UAC if needed"); QMessageBox::information(NULL,"Debug",message); } ////////////////////////////// First way to load ////////////////////////////// wchar_t arrayArg[65535]; int size_lenght; // first try - load dll and register it manually. HRESULT hResult = S_OK; // if failed - try by loading extension manually (would fail on vista when running as user) hResult = CoInitializeEx(NULL, COINIT_MULTITHREADED); if(SUCCEEDED(hResult)) { HRESULT (STDAPICALLTYPE *pfn)(void); size_lenght=dllPath.toWCharArray(arrayArg); HINSTANCE hMod = LoadLibrary(arrayArg); // load the dll if(hMod == NULL) hResult = HRESULT_FROM_WIN32(GetLastError()); if(SUCCEEDED(hResult) && !hMod) hResult = E_FAIL; if(SUCCEEDED(hResult)) { (FARPROC&)pfn = GetProcAddress(hMod, (bRegister ? "DllRegisterServer" : "DllUnregisterServer")); if(pfn == NULL) hResult = E_FAIL; if(SUCCEEDED(hResult)) hResult = (*pfn)(); CoFreeLibrary(hMod); } CoUninitialize(); if(SUCCEEDED(hResult) && SCODE_CODE(hResult) != ERROR_ACCESS_DENIED) return true; else ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,QString("fail by LoadLibrary: %1, error code: %2").arg(dllPath).arg((quint32)hResult)); } else ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,QString("fail by CoInitializeEx: %1, error code: %2").arg(dllPath).arg((quint32)hResult)); ////////////////////////////// Second way to load ////////////////////////////// QStringList arguments; if(!Debug) arguments.append("/s"); if(!bRegister) arguments.append("/u"); arguments.append(dllPath); QString argumentsString; for (int i = 0; i < arguments.size(); ++i) { if(argumentsString.isEmpty()) argumentsString+=arguments.at(i); else if(i == arguments.size()) argumentsString+=" \""+arguments.at(i)+"\""; else argumentsString+=' '+arguments.at(i); } ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"start: regsvr32 "+argumentsString); int result=QProcess::execute("regsvr32",arguments); bool ok=false; if(result==0) ok=true; #if ! defined(_M_X64) if(result==999 && !changeOfArchDetected)//code of wrong arch for the dll { changeOfArchDetected=true; QStringList temp; temp = importantDll; secondDll = importantDll; importantDll = temp; return false; } #endif if(result==5) { if(!quiet || (!bRegister && correctlyLoaded.contains(dllPath))) { ////////////////////////////// Last way to load ////////////////////////////// ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"try it in win32"); // try with regsvr32, win32 because for admin dialog size_lenght=argumentsString.toWCharArray(arrayArg); //size_lenght*sizeof(wchar_t) wcscpy(arrayArg+size_lenght*sizeof(wchar_t),TEXT("\0")); SHELLEXECUTEINFO sei; memset(&sei, 0, sizeof(sei)); sei.cbSize = sizeof(sei); sei.fMask = SEE_MASK_UNICODE; sei.lpVerb = TEXT("runas"); sei.lpFile = TEXT("regsvr32.exe"); ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"in win32 mode: arrayArg: "+QString::fromWCharArray(arrayArg,size_lenght)); sei.lpParameters = arrayArg; sei.nShow = SW_SHOW; ok=ShellExecuteEx(&sei); } else ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,"not try because need be quiet: "+dllPath); } else ULTRACOPIER_DEBUGCONSOLE(DebugLevel_Notice,QString("regsvr32 terminated with: %1").arg(result)); correctlyLoaded.remove(dllPath); if(!bRegister) HardUnloadDLL(dllPath); return ok; }