解决window8不能播放flash的问题

来源:互联网 发布:虚拟化软件对比 编辑:程序博客网 时间:2024/04/27 16:11

windows8内置的flash播放控件,因为对Activex的支持不佳,很多基于flash Activex的软件无法正常运行。我们不可能要求用户安装某个版本的flash播放器,最好的方法就是无缝加载我们指定的ocx控件。


所贴代码仅限32位程序,64位程序修改钩子实现代码后应该也能用。适用于MFC程序,只需要在现有代码里增加少许代码即可。


1.安装适用版本的flash控件,把Windows\System32\Macromed\Flash\*.ocx拷贝出来,改名Flash32.ocx,和我们的主程序放一起。

2.在App类的实现cpp里添加两个全局函数,代码如下:


//实现加载我们指定的OCX文件。

HRESULT GetFlashObject(REFCLSID clsid, LPUNKNOWN pUnkOuter,
    DWORD dwClsCtx, REFIID iid, LPVOID* ppv, BSTR& bstrLicKey)
{
    HRESULT hr;
    static HMODULE hOcx = NULL;
    const TCHAR* pOcxName = _T("Flash32.ocx");
    if(!hOcx)
    {
        TCHAR szBuffer[_MAX_PATH];
        ::GetModuleFileName(NULL, szBuffer, _MAX_PATH);
        TCHAR* pExeName = _tcsrchr(szBuffer, _T('\\'));
        *++pExeName = 0;
        _tcscat(pExeName, pOcxName);
        hOcx = ::LoadLibrary(szBuffer);
    }

    typedef HRESULT (_stdcall* DllGetClassObjectPtr)(REFCLSID, REFIID, LPVOID);
    static DllGetClassObjectPtr pDllGetClassObject = NULL;
    if(!pDllGetClassObject && hOcx)
    {
        pDllGetClassObject = (DllGetClassObjectPtr)::GetProcAddress(hOcx, "DllGetClassObject");
    }

    if(!pDllGetClassObject)
    {
        return S_FALSE;
    }

    if (::SysStringLen(bstrLicKey) == 0)
    {
        LPCLASSFACTORY pClassFactory = NULL;

        if (SUCCEEDED(hr = pDllGetClassObject(clsid, IID_IClassFactory, (void**)&pClassFactory)))
        {
            ASSERT(pClassFactory != NULL);
            hr = pClassFactory->CreateInstance(pUnkOuter, iid, ppv);
            pClassFactory->Release();
        }
    }
    else
    {
        LPCLASSFACTORY2 pClassFactory = NULL;

        if (SUCCEEDED(hr = pDllGetClassObject(clsid, IID_IClassFactory2, (void**)&pClassFactory)))
        {
            ASSERT(pClassFactory != NULL);
            hr = pClassFactory->CreateInstanceLic(pUnkOuter, NULL, iid,
                bstrLicKey, ppv);
            pClassFactory->Release();
        }
    }
    return hr;
}

//实现加载Activex时的分发动作。
AFX_STATIC HRESULT AFXAPI MyCoCreateInstanceLic(REFCLSID clsid, LPUNKNOWN pUnkOuter,
    DWORD dwClsCtx, REFIID iid, LPVOID* ppv, BSTR bstrLicKey)
{
    HRESULT hr;
    static CLSID const swfid
        = { 0xD27CDB6E, 0xAE6D, 0x11CF, { 0x96, 0xB8, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0 } };
    if(swfid == clsid)
    {
        return GetFlashObject(clsid, pUnkOuter, dwClsCtx, iid, ppv, bstrLicKey);
    }

    if (::SysStringLen(bstrLicKey) == 0)
    {
        LPCLASSFACTORY pClassFactory = NULL;

        if (SUCCEEDED(hr = CoGetClassObject(clsid, dwClsCtx, NULL,
            IID_IClassFactory, (void**)&pClassFactory)))
        {
            ASSERT(pClassFactory != NULL);
            hr = pClassFactory->CreateInstance(pUnkOuter, iid, ppv);
            pClassFactory->Release();
        }
    }
    else
    {
        LPCLASSFACTORY2 pClassFactory = NULL;

        if (SUCCEEDED(hr = CoGetClassObject(clsid, dwClsCtx, NULL,
            IID_IClassFactory2, (void**)&pClassFactory)))
        {
            ASSERT(pClassFactory != NULL);
            hr = pClassFactory->CreateInstanceLic(pUnkOuter, NULL, iid,
                bstrLicKey, ppv);
            pClassFactory->Release();
        }
    }

    return hr;
}


在App类的构造函数里添加如下代码:

//挂钩_AfxCoCreateInstanceLic,不同VS版本,实现的流程可能不同,也可能不是_AfxCoCreateInstanceLic。

    extern HRESULT AFXAPI _AfxCoCreateInstanceLic(REFCLSID clsid, LPUNKNOWN pUnkOuter,
        DWORD dwClsCtx, REFIID iid, LPVOID* ppv, BSTR bstrLicKey);
    ASSERT(sizeof(long) == 4);
    long lFunOld = (long)_AfxCoCreateInstanceLic;
    long lFunNew = (long)MyCoCreateInstanceLic;
    BYTE nCodes[5] = {0xE9, 0};
    long* pAddress = (long*)&nCodes[1];
    *pAddress = lFunNew - lFunOld - 5;
    SIZE_T nSize = sizeof(nCodes);
    DWORD dwProtect = PAGE_EXECUTE_READWRITE;
    VirtualProtect((LPVOID)lFunOld, nSize, dwProtect, &dwProtect);
    WriteProcessMemory(GetCurrentProcess(), (LPVOID)lFunOld, nCodes, nSize, &nSize);
    VirtualProtect((LPVOID)lFunOld, nSize, dwProtect, &dwProtect);

从原理上讲,该方法应该适用于所有Activex的自定义加载。


原创粉丝点击