Exemple #1
0
void SetupD3D101(IDXGISwapChain *swapChain)
{
    logOutput << CurrentTimeString() << "setting up d3d10.1 data" << endl;
    ClearD3D101Data();

    DXGI_SWAP_CHAIN_DESC scd;
    if(SUCCEEDED(swapChain->GetDesc(&scd)))
    {
        d3d101CaptureInfo.format = ConvertGIBackBufferFormat(scd.BufferDesc.Format);
        if(d3d101CaptureInfo.format != GS_UNKNOWNFORMAT)
        {
            if( dxgiFormat                    != scd.BufferDesc.Format ||
                d3d101CaptureInfo.cx          != scd.BufferDesc.Width  ||
                d3d101CaptureInfo.cy          != scd.BufferDesc.Height ||
                d3d101CaptureInfo.hwndCapture != (DWORD)scd.OutputWindow)
            {
                dxgiFormat = FixCopyTextureFormat(scd.BufferDesc.Format);
                d3d101CaptureInfo.cx = scd.BufferDesc.Width;
                d3d101CaptureInfo.cy = scd.BufferDesc.Height;
                d3d101CaptureInfo.hwndCapture = (DWORD)scd.OutputWindow;
                bIsMultisampled = scd.SampleDesc.Count > 1;

                logOutput << CurrentTimeString() << "found dxgi format (dx10.1) of: " << UINT(dxgiFormat) <<
                    ", size: {" << scd.BufferDesc.Width << ", " << scd.BufferDesc.Height <<
                    "}, multisampled: " << (bIsMultisampled ? "true" : "false") << endl;
            }
        }
    }

    lastTime = 0;
    OSInitializeTimer();
}
Exemple #2
0
inline bool AttemptToHookSomething()
{
    bool bFoundSomethingToHook = false;
    if(!bD3D9Hooked && InitD3D9Capture())
    {
        logOutput << CurrentTimeString() << "D3D9 Present" << endl;
        bFoundSomethingToHook = true;
        bD3D9Hooked = true;
    }
    if(!bDXGIHooked && InitDXGICapture())
    {
        logOutput << CurrentTimeString() << "DXGI Present" << endl;
        bFoundSomethingToHook = true;
        bDXGIHooked = true;
    }
    if(!bGLHooked && InitGLCapture())
    {
        logOutput << CurrentTimeString() << "GL Present" << endl;
        bFoundSomethingToHook = true;
        bGLHooked = true;
    }
    /*
    if(!bDirectDrawHooked && InitDDrawCapture())
    {
        OutputDebugString(TEXT("DirectDraw Present\r\n"));
        bFoundSomethingToHook = true;
        bDirectDrawfHooked = true;
    }*/

    return bFoundSomethingToHook;
}
Exemple #3
0
HRESULT STDMETHODCALLTYPE CreateSurface(IDirectDraw7* ddInterface, LPDDSURFACEDESC2 lpDDSurfaceDesc, LPDIRECTDRAWSURFACE7 *lplpDDSurface, IUnknown *pUnkOuter)
{
    //logOutput << CurrentTimeString() << "Hooked CreateSurface()" << endl;

    if (!g_ddInterface)
    {
        if (ddInterface->QueryInterface(IID_IDirectDraw, (LPVOID*)&g_ddInterface) == S_OK)
        {
            logOutput << CurrentTimeString() << "IDirectDraw::CreateSurface: got DDInterface pointer" << endl;
        }
        else
        {
            logOutput << CurrentTimeString() << "IDirectDraw::CreateSurface: could not query DirectDraw interface" << endl;
        }
    }

    ddrawSurfaceCreate.Unhook();
    HRESULT hRes = ddInterface->CreateSurface(lpDDSurfaceDesc, lplpDDSurface, pUnkOuter);
    ddrawSurfaceCreate.Rehook();

    if (hRes == DD_OK)
    {
        if (lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
        {
            logOutput << CurrentTimeString() << "IDirectDraw::CreateSurface: Primary surface created at 0x" << *lplpDDSurface << endl;
            getFrontSurface(*lplpDDSurface);
        }
    }
    else
        printDDrawError(hRes, "CreateSurface");

    return hRes;
}
Exemple #4
0
bool DoD3D101Hook(ID3D10Device *device)
{
    HRESULT hErr;

    D3D10_TEXTURE2D_DESC texGameDesc;
    ZeroMemory(&texGameDesc, sizeof(texGameDesc));
    texGameDesc.Width               = d3d101CaptureInfo.cx;
    texGameDesc.Height              = d3d101CaptureInfo.cy;
    texGameDesc.MipLevels           = 1;
    texGameDesc.ArraySize           = 1;
    texGameDesc.Format              = dxgiFormat;
    texGameDesc.SampleDesc.Count    = 1;
    texGameDesc.BindFlags           = D3D10_BIND_RENDER_TARGET|D3D10_BIND_SHADER_RESOURCE;
    texGameDesc.Usage               = D3D10_USAGE_DEFAULT;
    texGameDesc.MiscFlags           = D3D10_RESOURCE_MISC_SHARED;

    ID3D10Texture2D *d3d101Tex;
    if(FAILED(hErr = device->CreateTexture2D(&texGameDesc, NULL, &d3d101Tex)))
    {
        RUNEVERYRESET logOutput << CurrentTimeString() << "DoD3D101Hook: failed to create intermediary texture, result = " << UINT(hErr) << endl;
        return false;
    }

    if(FAILED(hErr = d3d101Tex->QueryInterface(__uuidof(ID3D10Resource), (void**)&copyD3D101TextureGame)))
    {
        RUNEVERYRESET logOutput << CurrentTimeString() << "DoD3D101Hook: d3d101Tex->QueryInterface(ID3D10Resource) failed, result = " << UINT(hErr) << endl;
        d3d101Tex->Release();
        return false;
    }

    IDXGIResource *res;
    if(FAILED(hErr = d3d101Tex->QueryInterface(IID_IDXGIResource, (void**)&res)))
    {
        RUNEVERYRESET logOutput << CurrentTimeString() << "DoD3D101Hook: d3d101Tex->QueryInterface(IDXGIResource) failed, result = " << UINT(hErr) << endl;
        d3d101Tex->Release();
        return false;
    }

    if(FAILED(res->GetSharedHandle(&sharedHandle)))
    {
        RUNEVERYRESET logOutput << CurrentTimeString() << "DoD3D101Hook: res->GetSharedHandle failed, result = " << UINT(hErr) << endl;
        d3d101Tex->Release();
        res->Release();
        return false;
    }

    d3d101Tex->Release();
    res->Release();

    return true;
}
Exemple #5
0
    void Free()
    {
        bool bWait = true;

        // try locking mutexes so we don't accidently free memory used by copythread
        HANDLE mutexes[2];
        for (int i = 0; i < 2; i++)
        {
            if (!DuplicateHandle(GetCurrentProcess(), textureMutexes[i], GetCurrentProcess(), &mutexes[i], NULL, FALSE, DUPLICATE_SAME_ACCESS))
            {
                logOutput << CurrentTimeString() << "Palette::Free(): could not duplicate textureMutex handles, assuming OBS was closed and copy thread finished" << endl;
                bWait = false;
                break;
            }
        }

        // wait 2 seconds before deleting memory
        DWORD ret = WaitForMultipleObjects(2, mutexes, TRUE, 2000);

        destroy();

        if (bWait)
        {
            if (ret == WAIT_OBJECT_0)
            {
                ReleaseMutex(mutexes[0]);
                ReleaseMutex(mutexes[1]);
            }

            CloseHandle(mutexes[0]);
            CloseHandle(mutexes[1]);
        }
    }
void LogPresentParams(D3DPRESENT_PARAMETERS &pp)
{
    string strTime = CurrentTimeString();

    /*if (pp.hDeviceWindow) {
        UINT testLen = GetWindowTextLength(pp.hDeviceWindow);
        testLen++;

        string strName;
        strName.resize(testLen);
        GetWindowTextA(pp.hDeviceWindow, (char*)strName.c_str(), testLen);

        logOutput << CurrentTimeString() << "found d3d9 present params for window: " << strName << endl;
    }*/

    logOutput << strTime << "D3DPRESENT_PARAMETERS {" << endl;
    logOutput << strTime << "\t" "BackBufferWidth: " << pp.BackBufferWidth << endl;
    logOutput << strTime << "\t" "BackBufferHeight: " << pp.BackBufferHeight << endl;
    logOutput << strTime << "\t" "BackBufferFormat: " << GetD3D9FormatName(pp.BackBufferFormat) << endl;
    logOutput << strTime << "\t" "BackBufferCount: " << pp.BackBufferCount << endl;
    logOutput << strTime << "\t" "MultiSampleType: " << GetD3D9MultiSampleTypeName(pp.MultiSampleType) << endl;
    logOutput << strTime << "\t" "MultiSampleQuality: " << pp.MultiSampleQuality << endl;
    logOutput << strTime << "\t" "SwapEffect: " << GetD3D9SwapEffectName(pp.SwapEffect) << endl;
    logOutput << strTime << "\t" "hDeviceWindow: " << DWORD(pp.hDeviceWindow) << endl;
    logOutput << strTime << "\t" "Windowed: " << (pp.Windowed ? "true" : "false") << endl;
    logOutput << strTime << "\t" "EnableAutoDepthStencil: " << (pp.EnableAutoDepthStencil ? "true" : "false") << endl;
    logOutput << strTime << "\t" "AutoDepthStencilFormat: " << GetD3D9FormatName(pp.AutoDepthStencilFormat) << endl;
    logOutput << strTime << "\t" "Flags: " << GetD3D9D3DPPFlagsString(pp.Flags) << endl;
    logOutput << strTime << "\t" "FullScreen_RefreshRateInHz: " << pp.FullScreen_RefreshRateInHz << endl;
    logOutput << strTime << "\t" "PresentationInterval: " << pp.PresentationInterval << endl;
    logOutput << strTime << "};" << endl;
}
Exemple #7
0
inline bool AttemptToHookSomething()
{
    if (!hwndSender || !hwndD3DDummyWindow || !hwndOpenGLSetupWindow)
        return false;

    bool bFoundSomethingToHook = false;
    if(!bD3D9Hooked) {
        if (InitD3D9Capture()) {
            logOutput << CurrentTimeString() << "D3D9 Present" << endl;
            bFoundSomethingToHook = true;
            bD3D9Hooked = true;
        }
    } else {
        //occasionally, certain applications can reset the d3d9 hook, or clear it, or something.
        //so, we forcibly make sure that the d3d9 function is still hooked.
        CheckD3D9Capture();
    }

    if(!bDXGIHooked && InitDXGICapture())
    {
        logOutput << CurrentTimeString() << "DXGI Present" << endl;
        bFoundSomethingToHook = true;
        bDXGIHooked = true;
    }
    if(!bGLHooked && InitGLCapture()) {
        logOutput << CurrentTimeString() << "GL Present" << endl;
        bFoundSomethingToHook = true;
        bGLHooked = true;
    } else {
        CheckGLCapture();
    }
    /*
    if(!bDirectDrawHooked && InitDDrawCapture())
    {
        OutputDebugString(TEXT("DirectDraw Present\r\n"));
        bFoundSomethingToHook = true;
        bDirectDrawfHooked = true;
    }*/

    return bFoundSomethingToHook;
}
Exemple #8
0
inline HRESULT STDMETHODCALLTYPE UnlockSurface(LPDIRECTDRAWSURFACE7 surface, LPRECT data)
{
    //logOutput << CurrentTimeString() << "Called UnlockSurface" << endl;

    // standard handler
    if (!bTargetAcquired)
    {
        ddrawSurfaceUnlock.Unhook();
        HRESULT hr = surface->Unlock(data);
        ddrawSurfaceUnlock.Rehook();
        return hr;
    }

    // use mutex lock to prevent memory corruption when calling Unhook/Rehook from multiple threads
    HANDLE mutex = OpenMutex(SYNCHRONIZE, FALSE, mutexName);
    if (!mutex)
    {
        logOutput << CurrentTimeString() << "Could not open mutex - Error(" << GetLastError() << ')' << endl;
        return DDERR_GENERIC;
    }

    DWORD ret = WaitForSingleObject(mutex, INFINITE);
    if (ret == WAIT_OBJECT_0)
    {
        ddrawSurfaceUnlock.Unhook();
        HRESULT hr = surface->Unlock(data);
        ddrawSurfaceUnlock.Rehook();

        ReleaseMutex(mutex);
        CloseHandle(mutex);
        return hr;
    }
    else
    {
        logOutput << CurrentTimeString() << "error while waiting for unlock-mutex to get signaled" << endl;
        logOutput << CurrentTimeString() << "GetLastError: " << GetLastError() << endl;
        CloseHandle(mutex);
        return DDERR_GENERIC;
    }
}
Exemple #9
0
HRESULT STDMETHODCALLTYPE Restore(LPDIRECTDRAWSURFACE7 surface)
{
    //logOutput << CurrentTimeString() << "Hooked Restore()" << endl;

    ddrawSurfaceRestore.Unhook();
    HRESULT hr = surface->Restore();

    if (bHasTextures)
    {
        if (surface == g_frontSurface)
        {
            logOutput << CurrentTimeString() << "SurfaceRestore: restoring offscreen buffers" << endl;
            bool success = true;
            for (UINT i = 0; i < NUM_BUFFERS; i++)
            {
                HRESULT err;
                if (FAILED(err = ddCaptures[i]->Restore()))
                {
                    logOutput << CurrentTimeString() << "SurfaceRestore: error restoring offscreen buffer" << endl;
                    printDDrawError(err, "Restore");
                    success = false;
                }
            }
            if (!success)
            {
                CleanUpDDraw();
            }
        }
    }
    ddrawSurfaceRestore.Rehook();

    if (!bHasTextures)
    {
        getFrontSurface(surface);
    }

    return hr;
}
Exemple #10
0
    void ReloadPrimarySurfacePaletteEntries()
    {
        if (!primary_surface_palette_ref)
            return;

        HRESULT err;
        ddrawPaletteSetEntries.Unhook();
        if (FAILED(err = primary_surface_palette_ref->SetEntries(0, 0, numEntries, entries)))
        {
            logOutput << CurrentTimeString() << "ReloadPrimarySurfacePaletteEntries(): could not set entires" << endl;
            printDDrawError(err);
        }
        ddrawPaletteSetEntries.Rehook();
    }
Exemple #11
0
void ClearD3D101Data()
{
    bHasTextures = false;
    texData = NULL;
    sharedHandle = NULL;

    SafeRelease(copyD3D101TextureGame);

    DestroySharedMemory();
    keepAliveTime = 0;
    resetCount++;

    logOutput << CurrentTimeString() << "---------------------- Cleared D3D10.1 Capture ----------------------" << endl;
}
Exemple #12
0
DWORD CopyGLCPUTextureThread(LPVOID lpUseless)
{
    int sharedMemID = 0;

    HANDLE hEvent = NULL;
    if(!DuplicateHandle(GetCurrentProcess(), hCopyEvent, GetCurrentProcess(), &hEvent, NULL, FALSE, DUPLICATE_SAME_ACCESS))
    {
        logOutput << CurrentTimeString() << "CopyGLCPUTextureThread: couldn't duplicate handle" << endl;
        return 0;
    }

    while(WaitForSingleObject(hEvent, INFINITE) == WAIT_OBJECT_0)
    {
        if(bKillThread)
            break;

        int nextSharedMemID = sharedMemID == 0 ? 1 : 0;

        DWORD copyTex = curCPUTexture;
        LPVOID data = pCopyData;
        if(copyTex < NUM_BUFFERS && data != NULL)
        {
            OSEnterMutex(glDataMutexes[copyTex]);

            int lastRendered = -1;

            //copy to whichever is available
            if(WaitForSingleObject(textureMutexes[sharedMemID], 0) == WAIT_OBJECT_0)
                lastRendered = (int)sharedMemID;
            else if(WaitForSingleObject(textureMutexes[nextSharedMemID], 0) == WAIT_OBJECT_0)
                lastRendered = (int)nextSharedMemID;

            if(lastRendered != -1)
            {
                memcpy(textureBuffers[lastRendered], data, glcaptureInfo.pitch*glcaptureInfo.cy);
                ReleaseMutex(textureMutexes[lastRendered]);
                copyData->lastRendered = (UINT)lastRendered;
            }

            OSLeaveMutex(glDataMutexes[copyTex]);
        }

        sharedMemID = nextSharedMemID;
    }

    CloseHandle(hEvent);
    return 0;
}
Exemple #13
0
void __cdecl Logva(const TCHAR *format, va_list argptr)
{
    if(!format) return;

    String strCurTime = CurrentTimeString();
    strCurTime << TEXT(": ");
    String strOut = strCurTime;
    strOut << FormattedStringva(format, argptr);

    strOut.FindReplace(TEXT("\n"), String() << TEXT("\n") << strCurTime);

    OpenLogFile();
    LogFile.WriteAsUTF8(strOut, strOut.Length());
    LogFile.WriteAsUTF8(TEXT("\r\n"));
    CloseLogFile();
}
void LogD3D9SurfaceInfo(IDirect3DSurface9 *surf)
{
    if (!surf) return;

    string strTime = CurrentTimeString();

    D3DSURFACE_DESC sd;
    ZeroMemory(&sd, sizeof(sd));
    if (SUCCEEDED(surf->GetDesc(&sd))) {
        logOutput << strTime << "D3DSURFACE_DESC {" << endl;
        logOutput << strTime << "\t" "Format: " << GetD3D9FormatName(sd.Format) << endl;
        logOutput << strTime << "\t" "Type: " << GetD3D9ResourceTypeName(sd.Type) << endl;
        logOutput << strTime << "\t" "Usage: " << GetD3D9UsageString(sd.Usage) << endl;
        logOutput << strTime << "\t" "Pool: " << GetD3D9PoolName(sd.Pool) << endl;
        logOutput << strTime << "\t" "MultiSampleType: " << GetD3D9MultiSampleTypeName(sd.MultiSampleType) << endl;
        logOutput << strTime << "\t" "MultiSampleQuality: " << sd.MultiSampleQuality << endl;
        logOutput << strTime << "\t" "Width: " << sd.Width << endl;
        logOutput << strTime << "\t" "Height: " << sd.Height << endl;
        logOutput << strTime << "};" << endl;
    } else {
        logOutput << strTime << "could not get D3DSURFACE_DESC from backbuffer for some reason" << endl;
    }
}
Exemple #15
0
ULONG STDMETHODCALLTYPE Release(LPDIRECTDRAWSURFACE7 surface)
{
    //logOutput << CurrentTimeString() << "Hooked Release()" << endl;

    ddrawSurfaceRelease.Unhook();
    /*
    if(surface == g_frontSurface)
    {
    logOutput << CurrentTimeString() << "Releasing primary surface 0x" << surface << endl;
    surface->AddRef();
    ULONG refCount = surface->Release();

    if(refCount == 1)
    {
    logOutput << CurrentTimeString() << "Freeing primary surface" << endl;
    g_frontSurface = NULL;
    bTargetAcquired = false;
    CleanUpDDraw();
    }
    }
    */

    ULONG refCount = surface->Release();
    ddrawSurfaceRelease.Rehook();

    if (surface == g_frontSurface)
    {
        if (refCount == 0)
        {
            logOutput << CurrentTimeString() << "Freeing primary surface" << endl;
            CleanUpDDraw();
        }
    }

    return refCount;
}
DWORD WINAPI CaptureThread(HANDLE hDllMainThread)
{
    bool bSuccess = false;

    //wait for dll initialization to finish before executing any initialization code
    if(hDllMainThread)
    {
        WaitForSingleObject(hDllMainThread, INFINITE);
        CloseHandle(hDllMainThread);
    }

    TCHAR lpLogPath[MAX_PATH];
    SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, lpLogPath);
    wcscat_s(lpLogPath, MAX_PATH, TEXT("\\OBS\\pluginData\\captureHookLog.txt"));

    dummyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

    if(!logOutput.is_open())
        logOutput.open(lpLogPath, ios_base::in | ios_base::out | ios_base::trunc, _SH_DENYNO);

    wstringstream str;
    str << OBS_KEEPALIVE_EVENT << UINT(GetCurrentProcessId());
    strKeepAlive = str.str();

    logOutput << CurrentDateTimeString() << "we're booting up: " << endl;

    InitializeCriticalSection(&d3d9EndMutex);
    InitializeCriticalSection(&glMutex);

    WNDCLASS wc;
    ZeroMemory(&wc, sizeof(wc));
    wc.hInstance = hinstMain;
    wc.lpszClassName = SENDER_WINDOWCLASS;
    wc.lpfnWndProc = (WNDPROC)DefWindowProc;

    DWORD procID = GetCurrentProcessId();

    wstringstream strRestartEvent, strEndEvent, strReadyEvent, strExitEvent, strInfoMemory;
    strRestartEvent << RESTART_CAPTURE_EVENT << procID;
    strEndEvent     << END_CAPTURE_EVENT     << procID;
    strReadyEvent   << CAPTURE_READY_EVENT   << procID;
    strExitEvent    << APP_EXIT_EVENT        << procID;
    strInfoMemory   << INFO_MEMORY           << procID;

    hSignalRestart  = GetEvent(strRestartEvent.str().c_str());
    hSignalEnd      = GetEvent(strEndEvent.str().c_str());
    hSignalReady    = GetEvent(strReadyEvent.str().c_str());
    hSignalExit     = GetEvent(strExitEvent.str().c_str());

    hInfoFileMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(CaptureInfo), strInfoMemory.str().c_str());
    if(!hInfoFileMap)
    {
        logOutput << CurrentTimeString() << "CaptureThread: could not info file mapping" << endl;
        return 0;
    }

    infoMem = (CaptureInfo*)MapViewOfFile(hInfoFileMap, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(CaptureInfo));
    if(!infoMem)
    {
        logOutput << CurrentTimeString() << "CaptureThread: could not map view of info shared memory" << endl;
        CloseHandle(hInfoFileMap);
        hInfoFileMap = NULL;
        return 0;
    }

    hwndOBS = FindWindow(OBS_WINDOW_CLASS, NULL);
    if(!hwndOBS)
    {
        logOutput << CurrentTimeString() << "CaptureThread: could not find main application window?  wtf?  seriously?" << endl;
        return 0;
    }

    if (RegisterClass(&wc)) {
        hwndSender = CreateWindow(SENDER_WINDOWCLASS, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, hinstMain, 0);
        if (hwndSender) {
            textureMutexes[0] = OpenMutex(MUTEX_ALL_ACCESS, FALSE, TEXTURE_MUTEX1);
            if (textureMutexes[0]) {
                textureMutexes[1] = OpenMutex(MUTEX_ALL_ACCESS, FALSE, TEXTURE_MUTEX2);
                if (textureMutexes[1]) {
                    while(!AttemptToHookSomething())
                        Sleep(50);

                    logOutput << CurrentTimeString() << "(half life scientist) everything..  seems to be in order" << endl;

                    MSG msg;
                    while (MsgWaitForMultipleObjects(1, &dummyEvent, FALSE, 3000, QS_ALLINPUT) != WAIT_ABANDONED_0) {
                    //while (GetMessageTimeout(msg, 3000)) {
                        AttemptToHookSomething();
                        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
                            TranslateMessage(&msg);
                            DispatchMessage(&msg);
                        }
                    }

                    CloseHandle(textureMutexes[1]);
                    textureMutexes[1] = NULL;
                } else {
                    logOutput << CurrentTimeString() << "could not open texture mutex 2" << endl;
                }

                CloseHandle(textureMutexes[0]);
                textureMutexes[0] = NULL;
            } else {
                logOutput << CurrentTimeString() << "could not open texture mutex 1" << endl;
            }

            DestroyWindow(hwndSender);
        } else {
            logOutput << CurrentTimeString() << "could not create sender window" << endl;
        }
    }

    logOutput << CurrentTimeString() << "WARNING: exit out of the main thread loop somehow" << endl;

    return 0;
}
Exemple #17
0
DWORD WINAPI CaptureThread(HANDLE hDllMainThread)
{
    bool bSuccess = false;

    //wait for dll initialization to finish before executing any initialization code
    if(hDllMainThread)
    {
        WaitForSingleObject(hDllMainThread, INFINITE);
        CloseHandle(hDllMainThread);
    }

    TCHAR lpLogPath[MAX_PATH];
    SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, lpLogPath);
    wcscat_s(lpLogPath, MAX_PATH, TEXT("\\OBS\\pluginData\\captureHookLog.txt"));

    dummyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

    if(!logOutput.is_open())
        logOutput.open(lpLogPath, ios_base::in | ios_base::out | ios_base::trunc, _SH_DENYNO);

    wstringstream str;
    str << OBS_KEEPALIVE_EVENT << UINT(GetCurrentProcessId());
    strKeepAlive = str.str();

    logOutput << CurrentDateTimeString() << "we're booting up: " << endl;

    InitializeCriticalSection(&d3d9EndMutex);
    InitializeCriticalSection(&glMutex);

    DWORD procID = GetCurrentProcessId();

    wstringstream strRestartEvent, strEndEvent, strReadyEvent, strExitEvent, strInfoMemory;
    strRestartEvent << RESTART_CAPTURE_EVENT << procID;
    strEndEvent     << END_CAPTURE_EVENT     << procID;
    strReadyEvent   << CAPTURE_READY_EVENT   << procID;
    strExitEvent    << APP_EXIT_EVENT        << procID;
    strInfoMemory   << INFO_MEMORY           << procID;

    hSignalRestart  = GetEvent(strRestartEvent.str().c_str());
    hSignalEnd      = GetEvent(strEndEvent.str().c_str());
    hSignalReady    = GetEvent(strReadyEvent.str().c_str());
    hSignalExit     = GetEvent(strExitEvent.str().c_str());

    DWORD bla;
    HANDLE hWindowThread = CreateThread(NULL, 0, DummyWindowThread, NULL, 0, &bla);
    if (!hWindowThread) {
        logOutput << CurrentTimeString() << "CaptureThread: could not create window thread for some reason" << endl;
        return 0;
    }

    CloseHandle(hWindowThread);

    hInfoFileMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(CaptureInfo), strInfoMemory.str().c_str());
    if(!hInfoFileMap)
    {
        logOutput << CurrentTimeString() << "CaptureThread: could not info file mapping" << endl;
        return 0;
    }

    infoMem = (CaptureInfo*)MapViewOfFile(hInfoFileMap, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(CaptureInfo));
    if(!infoMem)
    {
        logOutput << CurrentTimeString() << "CaptureThread: could not map view of info shared memory" << endl;
        CloseHandle(hInfoFileMap);
        hInfoFileMap = NULL;
        return 0;
    }

    hwndOBS = FindWindow(OBS_WINDOW_CLASS, NULL);
    if(!hwndOBS)
    {
        logOutput << CurrentTimeString() << "CaptureThread: could not find main application window?  wtf?  seriously?" << endl;
        return 0;
    }

    textureMutexes[0] = OpenMutex(MUTEX_ALL_ACCESS, FALSE, TEXTURE_MUTEX1);
    if (textureMutexes[0]) {
        textureMutexes[1] = OpenMutex(MUTEX_ALL_ACCESS, FALSE, TEXTURE_MUTEX2);
        if (textureMutexes[1]) {
            while(!AttemptToHookSomething())
                Sleep(50);

            logOutput << CurrentTimeString() << "(half life scientist) everything..  seems to be in order" << endl;

            while (1) {
                AttemptToHookSomething();
                Sleep(4000);
            }

            CloseHandle(textureMutexes[1]);
            textureMutexes[1] = NULL;
        } else {
            logOutput << CurrentTimeString() << "could not open texture mutex 2" << endl;
        }

        CloseHandle(textureMutexes[0]);
        textureMutexes[0] = NULL;
    } else {
        logOutput << CurrentTimeString() << "could not open texture mutex 1" << endl;
    }

    logOutput << CurrentTimeString() << "WARNING: exit out of the main thread loop somehow" << endl;

    return 0;
}
Exemple #18
0
void HandleGLSceneUpdate(HDC hDC)
{
    if(!bTargetAcquired && hdcAcquiredDC == NULL)
    {
        logOutput << CurrentTimeString() << "setting up gl data" << endl;
        PIXELFORMATDESCRIPTOR pfd;

        hwndTarget = WindowFromDC(hDC);

        int pixFormat = GetPixelFormat(hDC);
        DescribePixelFormat(hDC, pixFormat, sizeof(pfd), &pfd);

        if(pfd.cColorBits == 32 && hwndTarget)
        {
            bTargetAcquired = true;
            hdcAcquiredDC = hDC;
            glcaptureInfo.format = GS_BGR;
        }

        OSInitializeTimer();
    }

    if(hDC == hdcAcquiredDC)
    {
        if(bCapturing && WaitForSingleObject(hSignalEnd, 0) == WAIT_OBJECT_0)
            bStopRequested = true;

        if(bCapturing && !IsWindow(hwndOBS))
        {
            hwndOBS = NULL;
            bStopRequested = true;
        }

        if(bCapturing && bStopRequested)
        {
            RUNEVERYRESET logOutput << CurrentTimeString() << "stop requested, terminating gl capture" << endl;

            ClearGLData();
            bCapturing = false;
            bStopRequested = false;
            bReacquiring = false;
        }

        if(!bCapturing && WaitForSingleObject(hSignalRestart, 0) == WAIT_OBJECT_0)
        {
            hwndOBS = FindWindow(OBS_WINDOW_CLASS, NULL);
            if(hwndOBS)
                bCapturing = true;
        }

        RECT rc;
        GetClientRect(hwndTarget, &rc);

        if(bCapturing && bReacquiring)
        {
            if(lastCX != rc.right || lastCY != rc.bottom) //reset if continuing to size within the 3 seconds
            {
                reacquireStart = OSGetTimeMicroseconds();
                lastCX = rc.right;
                lastCY = rc.bottom;
            }

            if(OSGetTimeMicroseconds()-reacquireTime >= 3000000) { //3 second to reacquire
                RUNEVERYRESET logOutput << CurrentTimeString() << "reacquiring gl due to resize..." << endl;
                bReacquiring = false;
            } else {
                return;
            }
        }

        if(bCapturing && (!bHasTextures || rc.right != glcaptureInfo.cx || rc.bottom != glcaptureInfo.cy))
        {
            if (!rc.right || !rc.bottom)
                return;

            if(bHasTextures) //resizing
            {
                ClearGLData();
                bReacquiring = true;
                reacquireStart = OSGetTimeMicroseconds();
                lastCX = rc.right;
                lastCY = rc.bottom;
                return;
            }
            else
            {
                if(hwndOBS)
                    DoGLCPUHook(rc);
                else
                    ClearGLData();
            }
        }

        LONGLONG timeVal = OSGetTimeMicroseconds();

        //check keep alive state, dumb but effective
        if(bCapturing)
        {
            if (!keepAliveTime)
                keepAliveTime = timeVal;

            if((timeVal-keepAliveTime) > 5000000)
            {
                HANDLE hKeepAlive = OpenEvent(EVENT_ALL_ACCESS, FALSE, strKeepAlive.c_str());
                if (hKeepAlive) {
                    CloseHandle(hKeepAlive);
                } else {
                    ClearGLData();
                    logOutput << CurrentTimeString() << "Keepalive no longer found on gl, freeing capture data" << endl;
                    bCapturing = false;
                }

                keepAliveTime = timeVal;
            }
        }

        if(bHasTextures)
        {
            LONGLONG frameTime;
            if(bCapturing)
            {
                if(copyData)
                {
                    if(frameTime = copyData->frameTime)
                    {
                        LONGLONG timeElapsed = timeVal-lastTime;

                        if(timeElapsed >= frameTime)
                        {
                            lastTime += frameTime;
                            if(timeElapsed > frameTime*2)
                                lastTime = timeVal;

                            GLuint texture = gltextures[curCapture];
                            DWORD nextCapture = (curCapture == NUM_BUFFERS-1) ? 0 : (curCapture+1);

                            glReadBuffer(GL_BACK);
                            glBindBuffer(GL_PIXEL_PACK_BUFFER, texture);

                            if(glLockedTextures[curCapture])
                            {
                                OSEnterMutex(glDataMutexes[curCapture]);

                                glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
                                glLockedTextures[curCapture] = false;

                                OSLeaveMutex(glDataMutexes[curCapture]);
                            }

                            glReadPixels(0, 0, glcaptureInfo.cx, glcaptureInfo.cy, GL_BGRA, GL_UNSIGNED_BYTE, 0);

                            //----------------------------------

                            glBindBuffer(GL_PIXEL_PACK_BUFFER, gltextures[nextCapture]);
                            pCopyData = (void*)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
                            if(pCopyData)
                            {
                                curCPUTexture = nextCapture;
                                glLockedTextures[nextCapture] = true;

                                RUNEVERYRESET logOutput << CurrentTimeString() << "successfully capturing gl frames via RAM" << endl;

                                SetEvent(hCopyEvent);
                            } else {
                                RUNEVERYRESET logOutput << CurrentTimeString() << "one or more gl frames failed to capture for some reason" << endl;
                            }

                            //----------------------------------

                            glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);

                            curCapture = nextCapture;
                        }
                    }
                }
            }
            else {
                RUNEVERYRESET logOutput << CurrentTimeString() << "no longer capturing, terminating gl capture" << endl;
                ClearGLData();
            }
        }
    }
}
KString KString::CurrentDateTimeString()
{
	return DateTimeString(CurrentDateString(), CurrentTimeString());
}
Exemple #20
0
void DoD3D101Capture(IDXGISwapChain *swap)
{
    HRESULT hRes;

    ID3D10Device *device = NULL;
    if(SUCCEEDED(swap->GetDevice(__uuidof(ID3D10Device), (void**)&device)))
    {
        if(bCapturing && WaitForSingleObject(hSignalEnd, 0) == WAIT_OBJECT_0)
            bStopRequested = true;

        if(bCapturing && !IsWindow(hwndOBS))
        {
            hwndOBS = NULL;
            bStopRequested = true;
        }

        if(!lpCurrentDevice)
        {
            lpCurrentDevice = device;

            /*FARPROC oldRelease = GetVTable(device, (8/4));
            if(oldRelease != newD3D10Release)
            {
                oldD3D10Release = oldRelease;
                newD3D10Release = ConvertClassProcToFarproc((CLASSPROC)&D3D101Override::DeviceReleaseHook);
                SetVTable(device, (8/4), newD3D10Release);
            }*/
        }

        if(bCapturing && bStopRequested)
        {
            RUNEVERYRESET logOutput << CurrentTimeString() << "stop requested, terminating d3d10.1 capture" << endl;

            ClearD3D101Data();
            bCapturing = false;
            bStopRequested = false;
        }

        if(!bCapturing && WaitForSingleObject(hSignalRestart, 0) == WAIT_OBJECT_0)
        {
            hwndOBS = FindWindow(OBS_WINDOW_CLASS, NULL);
            if(hwndOBS)
                bCapturing = true;
        }

        if(!bHasTextures && bCapturing)
        {
            if(dxgiFormat && hwndOBS)
            {
                BOOL bSuccess = DoD3D101Hook(device);

                if(bSuccess)
                {
                    d3d101CaptureInfo.mapID = InitializeSharedMemoryGPUCapture(&texData);
                    if(!d3d101CaptureInfo.mapID)
                        bSuccess = false;
                }

                if(bSuccess)
                {
                    bHasTextures = true;
                    d3d101CaptureInfo.captureType = CAPTURETYPE_SHAREDTEX;
                    d3d101CaptureInfo.bFlip = FALSE;
                    texData->texHandle = (DWORD)sharedHandle;

                    memcpy(infoMem, &d3d101CaptureInfo, sizeof(CaptureInfo));
                    SetEvent(hSignalReady);

                    logOutput << CurrentTimeString() << "DoD3D101Hook: success" << endl;
                }
                else
                {
                    ClearD3D101Data();
                }
            }
        }

        LONGLONG timeVal = OSGetTimeMicroseconds();

        //check keep alive state, dumb but effective
        if(bCapturing)
        {
            if (!keepAliveTime)
                keepAliveTime = timeVal;

            if((timeVal-keepAliveTime) > 5000000)
            {
                HANDLE hKeepAlive = OpenEvent(EVENT_ALL_ACCESS, FALSE, strKeepAlive.c_str());
                if (hKeepAlive) {
                    CloseHandle(hKeepAlive);
                } else {
                    ClearD3D101Data();
                    logOutput << CurrentTimeString() << "Keepalive no longer found on d3d10.1, freeing capture data" << endl;
                    bCapturing = false;
                }

                keepAliveTime = timeVal;
            }
        }

        if(bHasTextures)
        {
            LONGLONG frameTime;
            if(bCapturing)
            {
                if(texData)
                {
                    if(frameTime = texData->frameTime)
                    {
                        LONGLONG timeElapsed = timeVal-lastTime;

                        if(timeElapsed >= frameTime)
                        {
                            lastTime += frameTime;
                            if(timeElapsed > frameTime*2)
                                lastTime = timeVal;

                            DWORD nextCapture = curCapture == 0 ? 1 : 0;

                            ID3D10Resource *backBuffer = NULL;
                            if(SUCCEEDED(hRes = swap->GetBuffer(0, IID_ID3D10Resource, (void**)&backBuffer)))
                            {
                                if(bIsMultisampled)
                                    device->ResolveSubresource(copyD3D101TextureGame, 0, backBuffer, 0, dxgiFormat);
                                else
                                    device->CopyResource(copyD3D101TextureGame, backBuffer);

                                RUNEVERYRESET logOutput << CurrentTimeString() << "successfully capturing d3d10.1 frames via GPU" << endl;

                                backBuffer->Release();
                            } else {
                                RUNEVERYRESET logOutput << CurrentTimeString() << "DoD3D101Capture: swap->GetBuffer failed: result = " << UINT(hRes) << endl;
                            }

                            curCapture = nextCapture;
                        }
                    }
                }
            } else {
                RUNEVERYRESET logOutput << CurrentTimeString() << "no longer capturing, terminating d3d10.1 capture" << endl;
                ClearD3D101Data();
            }
        }
    }

    SafeRelease(device);
}
Exemple #21
0
bool InitDDrawCapture()
{
    bool versionSupported = false;
    HMODULE hDDrawLib = NULL;
    if (hDDrawLib = GetModuleHandle(TEXT("ddraw.dll")))
    {
        bool isWinVistaMin = IsWindowsVistaOrGreater();
        bool isWin7min = IsWindows7OrGreater();
        bool isWin8min = IsWindows8OrGreater();

        UPARAM libBaseAddr = UPARAM(hDDrawLib);
        UPARAM surfCreateOffset;
        UPARAM surfUnlockOffset;
        UPARAM surfReleaseOffset;
        UPARAM surfRestoreOffset;
        UPARAM surfBltOffset;
        UPARAM surfFlipOffset;
        UPARAM surfSetPaletteOffset;
        UPARAM palSetEntriesOffset;

        if (isWinVistaMin)
        {
            if (!isWin7min)
            {
                RUNEVERYRESET logOutput << CurrentTimeString() << "Windows Vista not supported yet" << endl;
            }
            else if (isWin7min && !isWin8min)
            {
                surfCreateOffset = 0x617E;
                surfUnlockOffset = 0x4C40;
                surfReleaseOffset = 0x3239;
                surfRestoreOffset = 0x3E9CB;
                surfBltOffset = surfCreateOffset + 0x44F63;
                surfFlipOffset = surfCreateOffset + 0x37789;
                surfSetPaletteOffset = surfCreateOffset + 0x4D2D3;
                palSetEntriesOffset = surfCreateOffset + 0x4CE68;
                versionSupported = true;
            }
            else if (isWin8min)
            {
                surfCreateOffset = 0x9530 + 0xC00;
                surfUnlockOffset = surfCreateOffset + 0x2A1D0;
                surfReleaseOffset = surfCreateOffset - 0x1A80;
                surfRestoreOffset = surfCreateOffset + 0x36000;
                surfBltOffset = surfCreateOffset + 0x438DC;
                surfFlipOffset = surfCreateOffset + 0x33EF3;
                surfSetPaletteOffset = surfCreateOffset + 0x4D3B8;
                palSetEntriesOffset = surfCreateOffset + 0x4CF4C;
                versionSupported = false;	// some crash bugs remaining

                RUNEVERYRESET logOutput << CurrentTimeString() << "Windows 8 not supported yet" << endl;
            }
            else
            {
                RUNEVERYRESET logOutput << CurrentTimeString() << "Unknown OS version" << endl;
            }
        }
        else
        {
            RUNEVERYRESET logOutput << CurrentTimeString() << "OS version not supported" << endl;
        }

        if (versionSupported)
        {
            ddrawSurfaceCreate.Hook((FARPROC)(libBaseAddr + surfCreateOffset), (FARPROC)CreateSurface);
            ddrawSurfaceRestore.Hook((FARPROC)(libBaseAddr + surfRestoreOffset), (FARPROC)Restore);
            ddrawSurfaceRelease.Hook((FARPROC)(libBaseAddr + surfReleaseOffset), (FARPROC)Release);
            ddrawSurfaceUnlock.Hook((FARPROC)(libBaseAddr + surfUnlockOffset), (FARPROC)Unlock);
            ddrawSurfaceBlt.Hook((FARPROC)(libBaseAddr + surfBltOffset), (FARPROC)Blt);
            ddrawSurfaceFlip.Hook((FARPROC)(libBaseAddr + surfFlipOffset), (FARPROC)Flip);
            ddrawSurfaceSetPalette.Hook((FARPROC)(libBaseAddr + surfSetPaletteOffset), (FARPROC)SetPalette);
            ddrawPaletteSetEntries.Hook((FARPROC)(libBaseAddr + palSetEntriesOffset), (FARPROC)PaletteSetEntries);

            ddrawSurfaceUnlock.Rehook();
            ddrawSurfaceFlip.Rehook();
            ddrawSurfaceBlt.Rehook();
            /*
            ddrawSurfaceCreate.Rehook();
            ddrawSurfaceRestore.Rehook();
            ddrawSurfaceRelease.Rehook();
            ddrawSurfaceSetPalette.Rehook();
            ddrawPaletteSetEntries.Rehook();
            */
        }
    }

    return versionSupported;
}
Exemple #22
0
void printDDrawError(HRESULT err, const char* callerName = "")
{
    if (err == DD_OK)
        return;

    std::string s;
    switch (err)
    {
    case DDERR_CANTCREATEDC: s = "can't create dc"; break;
    case DDERR_CANTLOCKSURFACE: s = "can't lock surface"; break;
    case DDERR_CLIPPERISUSINGHWND: s = "clipper is using hwnd"; break;
    case DDERR_COLORKEYNOTSET: s = "color key not set"; break;
    case DDERR_CURRENTLYNOTAVAIL: s = "currently not available"; break;
    case DDERR_DCALREADYCREATED: s = "dc already created"; break;
    case DDERR_DEVICEDOESNTOWNSURFACE: s = "device does not own surface"; break;
    case DDERR_DIRECTDRAWALREADYCREATED: s = "direct draw already created"; break;
    case DDERR_EXCLUSIVEMODEALREADYSET: s = "exclusive mode already set"; break;
    case DDERR_GENERIC: s = "undefined error"; break;
    case DDERR_HEIGHTALIGN: s = "height alignment is not a multiple of required alignment"; break;
    case DDERR_IMPLICITLYCREATED: s = "cannot restore surface, implicitly created"; break;
    case DDERR_INCOMPATIBLEPRIMARY: s = "incompatible primary"; break;
    case DDERR_INVALIDCAPS: s = "invalid caps"; break;
    case DDERR_INVALIDCLIPLIST: s = "invalid cliplist"; break;
    case DDERR_INVALIDMODE: s = "invalid mode"; break;
    case DDERR_INVALIDOBJECT: s = "invalid object"; break;
    case DDERR_INVALIDPARAMS: s = "invalid params"; break;
    case DDERR_INVALIDPIXELFORMAT: s = "invalid pixel format"; break;
    case DDERR_INVALIDPOSITION: s = "invalid position"; break;
    case DDERR_INVALIDRECT: s = "invalid rect"; break;
    case DDERR_LOCKEDSURFACES: s = "surface(s) locked"; break;
    case DDERR_MOREDATA: s = "data size exceeds buffer size"; break;
    case DDERR_NOALPHAHW: s = "no alpha acceleration hw available"; break;
    case DDERR_NOBLTHW: s = "no hw blit available"; break;
    case DDERR_NOCLIPLIST: s = "no cliplist available"; break;
    case DDERR_NOCLIPPERATTACHED: s = "no clipper attached"; break;
    case DDERR_NOCOLORCONVHW: s = "no color conversion hw available"; break;
    case DDERR_NOCOLORKEYHW: s = "no hw support for dest color key"; break;
    case DDERR_NOCOOPERATIVELEVELSET: s = "no cooperative level set"; break;
    case DDERR_NODC: s = "no dc available"; break;
    case DDERR_NOEXCLUSIVEMODE: s = "application does not have exclusive mode"; break;
    case DDERR_NOFLIPHW: s = "no hw flip available"; break;
    case DDERR_NOOVERLAYDEST: s = "GetOverlayPosition() is called but UpdateOverlay() has not been called"; break;
    case DDERR_NOOVERLAYHW: s = "no hw overlay available"; break;
    case DDERR_NOPALETTEATTACHED: s = "no palette attached"; break;
    case DDERR_NORASTEROPHW: s = "no raster operation hw available"; break;
    case DDERR_NOSTRETCHHW: s = "no hw support for stretching available"; break;
    case DDERR_NOTAOVERLAYSURFACE: s = "not an overlay component"; break;
    case DDERR_NOTFLIPPABLE: s = "surface not flippable"; break;
    case DDERR_NOTFOUND: s = "item not found"; break;
    case DDERR_NOTLOCKED: s = "surface not locked"; break;
    case DDERR_NOTPALETTIZED: s = "surface is not palette-based"; break;
    case DDERR_NOVSYNCHW: s = "no vsync hw available"; break;
    case DDERR_NOZOVERLAYHW: s = "not supported (NOZOVERLAYHW)"; break;
    case DDERR_OUTOFCAPS: s = "hw needed has already been allocated"; break;
    case DDERR_OUTOFMEMORY: s = "out of memory"; break;
    case DDERR_OUTOFVIDEOMEMORY: s = "out of video memory"; break;
    case DDERR_OVERLAPPINGRECTS: s = "overlapping rects on surface"; break;
    case DDERR_OVERLAYNOTVISIBLE: s = "GetOverlayPosition() is called on a hidden overlay"; break;
    case DDERR_PALETTEBUSY: s = "palette is locked by another thread"; break;
    case DDERR_PRIMARYSURFACEALREADYEXISTS: s = "primary surface already exists"; break;
    case DDERR_REGIONTOOSMALL: s = "region too small"; break;
    case DDERR_SURFACEBUSY: s = "surface is locked by another thread"; break;
    case DDERR_SURFACELOST: s = "surface lost"; break;
    case DDERR_TOOBIGHEIGHT: s = "requested height too large"; break;
    case DDERR_TOOBIGSIZE: s = "requested size too large"; break;
    case DDERR_TOOBIGWIDTH: s = "requested width too large"; break;
    case DDERR_UNSUPPORTED: s = "operation unsupported"; break;
    case DDERR_UNSUPPORTEDFORMAT: s = "unsupported pixel format"; break;
    case DDERR_VERTICALBLANKINPROGRESS: s = "vertical blank in progress"; break;
    case DDERR_VIDEONOTACTIVE: s = "video port not active"; break;
    case DDERR_WASSTILLDRAWING: s = "blit operation incomplete"; break;
    case DDERR_WRONGMODE: s = "surface cannot be restored because it was created in a different mode"; break;
    default: logOutput << "unknown error: " << getCodeFromHRESULT(err) << endl; return;
    }

    std::stringstream msg;
    msg << CurrentTimeString() << callerName << " DDraw Error: " << s << "\n";
    logOutput << msg.str();
}
Exemple #23
0
// set frontSurface to lpDDSurface if lpDDSurface is primary
// returns true if frontSurface is set
// returns false if frontSurface is NULL and lpDDSurface is not primary
bool getFrontSurface(LPDIRECTDRAWSURFACE7 lpDDSurface)
{
    //logOutput << CurrentTimeString() << "called getFrontSurface" << endl;

    if (!lpDDSurface)
    {
        //logOutput << CurrentTimeString() << "lpDDSurface null" << endl;
        return false;
    }

    if (!g_ddInterface)
    {
        LPDIRECTDRAWSURFACE7 dummy;
        if (lpDDSurface->QueryInterface(IID_IDirectDrawSurface7, (LPVOID*)&dummy) == S_OK)
        {
            IUnknown* Unknown;
            HRESULT err;
            if (FAILED(err = dummy->GetDDInterface((LPVOID*)&Unknown)))
            {
                logOutput << CurrentTimeString() << "getFrontSurface: could not get DirectDraw interface" << endl;
                printDDrawError(err, "getFrontSurface");
            }
            else
            {
                if (Unknown->QueryInterface(IID_IDirectDraw7, (LPVOID*)&g_ddInterface) == S_OK)
                {
                    logOutput << CurrentTimeString() << "Got DirectDraw interface pointer" << endl;
                }
                else
                {
                    logOutput << CurrentTimeString() << "Query of DirectDraw interface failed" << endl;
                }
            }
            ddrawSurfaceRelease.Unhook();
            dummy->Release();
            ddrawSurfaceRelease.Rehook();
        }
    }

    if (!bTargetAcquired)
    {
        DDSCAPS2 caps;
        if (SUCCEEDED(lpDDSurface->GetCaps(&caps)))
        {
            //logOutput << CurrentTimeString() << "checking if surface is primary" << endl;
            if (caps.dwCaps & DDSCAPS_PRIMARYSURFACE)
            {
                logOutput << CurrentTimeString() << "found primary surface" << endl;
                g_frontSurface = lpDDSurface;
                if (!SetupDDraw())
                {
                    return false;
                }
                else
                {
                    bTargetAcquired = true;
                }
            }
        }
        else
        {
            logOutput << CurrentTimeString() << "could not retrieve caps" << endl;
        }
    }

    return lpDDSurface == g_frontSurface;
}
Exemple #24
0
bool SetupDDraw()
{
    logOutput << CurrentTimeString() << "called SetupDDraw()" << endl;

    if (!g_ddInterface)
    {
        logOutput << CurrentTimeString() << "SetupDDraw: DirectDraw interface not set, returning" << endl;
        return false;
    }

    bool bSuccess = true;

    bKillThread = false;

    if (hCopyThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CopyDDrawTextureThread, NULL, 0, NULL))
    {
        if (!(hCopyEvent = CreateEvent(NULL, FALSE, FALSE, NULL)))
        {
            logOutput << CurrentTimeString() << "SetupDDraw: CreateEvent failed, GetLastError = " << GetLastError() << endl;
            bSuccess = false;
        }
    }
    else
    {
        logOutput << CurrentTimeString() << "SetupDDraw: CreateThread failed, GetLastError = " << GetLastError() << endl;
        bSuccess = false;
    }

    if (bSuccess)
    {
        if (!ddUnlockFctMutex)
        {
            ddUnlockFctMutex = CreateMutex(NULL, FALSE, mutexName);
            if (!ddUnlockFctMutex)
            {
                RUNEVERYRESET logOutput << CurrentTimeString() << "SetupDDraw: CreateMutex failed, GetLastError = " << GetLastError() << endl;
                bSuccess = false;
            }
        }
    }

    if (bSuccess && !g_frontSurface)
    {
        RUNEVERYRESET logOutput << "SetupDDraw: frontSurface and surface descriptor not set, returning" << endl;
        CleanUpDDraw();
        return false;
    }
    else if (bSuccess)
    {
        LPDIRECTDRAWPALETTE palette = NULL;
        HRESULT err;
        if (SUCCEEDED(err = g_frontSurface->GetPalette(&palette)))
        {
            if (palette)
                SetupPalette(palette);
        }
        else if (err == DDERR_NOPALETTEATTACHED)
        {
            //logOutput << CurrentTimeString() << "No palette attached to primary surface" << endl;
        }
        else
        {
            logOutput << CurrentTimeString() << "Error retrieving palette" << endl;
            printDDrawError(err, "getFrontSurface");
        }
    }

    if (bSuccess && !g_surfaceDesc)
    {
        logOutput << CurrentTimeString() << "SetupDDraw: no surface descriptor found, creating a new one (not an error)" << endl;

        g_surfaceDesc = new DDSURFACEDESC2;
        g_surfaceDesc->dwSize = sizeof(DDSURFACEDESC);

        HRESULT hr;
        if (FAILED(hr = ((LPDIRECTDRAWSURFACE)g_frontSurface)->GetSurfaceDesc((LPDDSURFACEDESC)g_surfaceDesc)))
        {
            g_surfaceDesc->dwSize = sizeof(DDSURFACEDESC2);
            if (FAILED(g_frontSurface->GetSurfaceDesc(g_surfaceDesc)))
            {
                logOutput << CurrentTimeString() << "SetupDDraw: error getting surface descriptor" << endl;
                printDDrawError(hr, "SetupDDraw");
                bSuccess = false;
            }
        }
    }

    if (bSuccess && g_surfaceDesc)
    {
        const DDPIXELFORMAT& pf = g_surfaceDesc->ddpfPixelFormat;
        if (pf.dwFlags & DDPF_RGB)
        {
            if (pf.dwRGBBitCount == 16)
            {
                logOutput << CurrentTimeString() << "SetupDDraw: found 16bit format (using R5G6B5 conversion)" << endl;
                g_bConvert16to32 = true;
            }
            else if (pf.dwRGBBitCount == 32)
            {
                logOutput << CurrentTimeString() << "SetupDDraw: found 32bit format (using plain copy)" << endl;
                g_bUse32bitCapture = true;
            }
        }
        else if (pf.dwFlags & (DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED2 | DDPF_PALETTEINDEXED1))
        {
            logOutput << CurrentTimeString() << "SetupDDraw: front surface uses palette indices" << endl;
        }
    }

    if (bSuccess)
    {
        logOutput << CurrentTimeString() << "SetupDDraw: primary surface width = " << g_surfaceDesc->dwWidth << ", height = " << g_surfaceDesc->dwHeight << endl;
        g_dwSize = g_surfaceDesc->lPitch*g_surfaceDesc->dwHeight;
        ddrawCaptureInfo.captureType = CAPTURETYPE_MEMORY;
        ddrawCaptureInfo.cx = g_surfaceDesc->dwWidth;
        ddrawCaptureInfo.cy = g_surfaceDesc->dwHeight;
        ddrawCaptureInfo.pitch = 4 * ddrawCaptureInfo.cx;
        ddrawCaptureInfo.hwndCapture = (DWORD)hwndSender;
        ddrawCaptureInfo.format = GS_BGRA;
        DWORD g_dwCaptureSize = ddrawCaptureInfo.pitch*ddrawCaptureInfo.cy;
        ddrawCaptureInfo.bFlip = FALSE;
        ddrawCaptureInfo.mapID = InitializeSharedMemoryCPUCapture(g_dwCaptureSize, &ddrawCaptureInfo.mapSize, &copyData, textureBuffers);

        memcpy(infoMem, &ddrawCaptureInfo, sizeof(CaptureInfo));

        DDSURFACEDESC2 captureDesc;
        ZeroMemory(&captureDesc, sizeof(captureDesc));
        captureDesc.dwSize = sizeof(DDSURFACEDESC2);

        captureDesc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_PITCH;
        captureDesc.dwWidth = g_surfaceDesc->dwWidth;
        captureDesc.dwHeight = g_surfaceDesc->dwHeight;
        captureDesc.lPitch = g_surfaceDesc->lPitch;
        captureDesc.ddpfPixelFormat = g_surfaceDesc->ddpfPixelFormat;
        captureDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;

        HRESULT err;

        ddrawSurfaceCreate.Unhook();
        for (int i = 0; i < NUM_BUFFERS && bSuccess; i++)
        {
            if (FAILED(err = g_ddInterface->CreateSurface(&captureDesc, &ddCaptures[i], NULL)))
            {
                logOutput << CurrentTimeString() << "SetupDDraw: Could not create offscreen capture" << endl;
                printDDrawError(err, "SetupDDraw");
                bSuccess = false;
                break;
            }
        }
        ddrawSurfaceCreate.Rehook();

        if (bSuccess)
        {
            bHasTextures = true;

            SetEvent(hSignalReady);

            OSInitializeTimer();
        }
    }

    if (bSuccess)
    {
        logOutput << CurrentTimeString() << "SetupDDraw successfull" << endl;
        HookAll();
        return true;
    }
    else
    {
        logOutput << CurrentTimeString() << "SetupDDraw failed" << endl;
        CleanUpDDraw();
        return false;
    }
}
Exemple #25
0
DWORD CopyDDrawTextureThread(LPVOID lpUseless)
{
    int sharedMemID = 0;

    HANDLE hEvent = NULL;
    if (!DuplicateHandle(GetCurrentProcess(), hCopyEvent, GetCurrentProcess(), &hEvent, NULL, FALSE, DUPLICATE_SAME_ACCESS))
    {
        logOutput << CurrentTimeString() << "CopyDDrawTextureThread: couldn't duplicate event handle - " << GetLastError() << endl;
        return 0;
    }

    std::stringstream msg;
    msg << CurrentTimeString() << "CopyDDrawTextureThread: waiting for copyEvents\n";
    logOutput << msg.str();
    msg.str("");
    while (WaitForSingleObject(hEvent, INFINITE) == WAIT_OBJECT_0)
    {
        //logOutput << CurrentTimeString() << "CopyDDrawTextureThread: received copyEvent" << endl;
        if (bKillThread)
            break;

        int nextSharedMemID = sharedMemID == 0 ? 1 : 0;

        DWORD copyTex = curCPUTexture;
        if (copyTex < NUM_BUFFERS)
        {
            //logOutput << CurrentTimeString() << "CopyDDrawTextureThread: processing data" << endl;
            int lastRendered = -1;

            //copy to whichever is available
            if (WaitForSingleObject(textureMutexes[sharedMemID], 0) == WAIT_OBJECT_0)
                lastRendered = (int)sharedMemID;
            else if (WaitForSingleObject(textureMutexes[nextSharedMemID], 0) == WAIT_OBJECT_0)
                lastRendered = (int)nextSharedMemID;

            if (lastRendered != -1)
            {
                //logOutput << CurrentTimeString() << "CopyDDrawTextureThread: copying to memfile" << endl;
                HRESULT err;
                DDSURFACEDESC2 desc;
                desc.dwSize = sizeof(desc);
                DWORD flags = DDLOCK_WAIT | DDLOCK_READONLY | DDLOCK_NOSYSLOCK;
                //logOutput << CurrentTimeString() << "CopyDDrawTextureThread: locking buffer" << endl;
                if (SUCCEEDED(err = ddCaptures[copyTex]->Lock(NULL, &desc, flags, NULL)))
                {
                    //logOutput << CurrentTimeString() << "CopyDDrawTextureThread: converting buffer" << endl;
                    handleBufferConversion((LPDWORD)textureBuffers[lastRendered], (LPBYTE)desc.lpSurface, desc.lPitch);
                    //logOutput << CurrentTimeString() << "CopyDDrawTextureThread: unlocking buffer" << endl;
                    if (FAILED(err = ddCaptures[copyTex]->Unlock(NULL)))
                    {
                        printDDrawError(err, "CopyDDrawTextureThread");
                    }
                    /*
                    else
                    logOutput << CurrentTimeString() << "CopyDDrawTextureThread: done" << endl;
                    */
                    //logOutput << CurrentTimeString() << "CopyDDrawTextureThread: finished uploading" << endl;
                }
                else
                {
                    RUNEVERYRESET logOutput << CurrentTimeString() << "CopyDDrawTextureThread: failed to lock capture surface" << endl;
                    printDDrawError(err, "CopyDDrawTextureThread");
                }
                ReleaseMutex(textureMutexes[lastRendered]);
                copyData->lastRendered = (UINT)lastRendered;
            }
        }

        sharedMemID = nextSharedMemID;
        //logOutput << CurrentTimeString() << "CopyDDrawTextureThread: waiting for event" << endl;
    }

    msg << CurrentTimeString() << "CopyDDrawTextureThread: killed\n";
    logOutput << msg.str();

    CloseHandle(hEvent);
    return 0;
}
Exemple #26
0
void DoGLCPUHook(RECT &rc)
{
    glcaptureInfo.cx = rc.right;
    glcaptureInfo.cy = rc.bottom;

    glGenBuffers(NUM_BUFFERS, gltextures);

    DWORD dwSize = glcaptureInfo.cx*glcaptureInfo.cy*4;

    BOOL bSuccess = true;
    for(UINT i=0; i<NUM_BUFFERS; i++)
    {
        UINT test = 0;

        glBindBuffer(GL_PIXEL_PACK_BUFFER, gltextures[i]);
        glBufferData(GL_PIXEL_PACK_BUFFER, dwSize, 0, GL_STREAM_READ);

        if(!(glDataMutexes[i] = OSCreateMutex()))
        {
            logOutput << CurrentTimeString() << "DoGLCPUHook: OSCreateMutex " << i << " failed, GetLastError = " << GetLastError();
            bSuccess = false;
            break;
        }
    }

    glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);

    if(bSuccess)
    {
        bKillThread = false;

        if(hCopyThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CopyGLCPUTextureThread, NULL, 0, NULL))
        {
            if(!(hCopyEvent = CreateEvent(NULL, FALSE, FALSE, NULL)))
            {
                logOutput << CurrentTimeString() << "DoGLCPUHook: CreateEvent failed, GetLastError = " << GetLastError();
                bSuccess = false;
            }
        }
        else
        {
            logOutput << CurrentTimeString() << "DoGLCPUHook: CreateThread failed, GetLastError = " << GetLastError();
            bSuccess = false;
        }
    }

    if(bSuccess)
    {
        glcaptureInfo.mapID = InitializeSharedMemoryCPUCapture(dwSize, &glcaptureInfo.mapSize, &copyData, textureBuffers);
        if(!glcaptureInfo.mapID)
            bSuccess = false;
    }

    if(bSuccess)
    {
        bHasTextures = true;
        glcaptureInfo.captureType = CAPTURETYPE_MEMORY;
        glcaptureInfo.hwndCapture = (DWORD)hwndTarget;
        glcaptureInfo.pitch = glcaptureInfo.cx*4;
        glcaptureInfo.bFlip = TRUE;

        memcpy(infoMem, &glcaptureInfo, sizeof(CaptureInfo));
        SetEvent(hSignalReady);

        logOutput << CurrentTimeString() << "DoGLCPUHook: success" << endl;

        OSInitializeTimer();
    }
    else
        ClearGLData();
}
Exemple #27
0
bool SetupPalette(LPDIRECTDRAWPALETTE lpDDPalette)
{
    if (!lpDDPalette)
    {
        //logOutput << CurrentTimeString() << "Detaching palette" << endl;
        g_CurrentPalette.Free();
        g_bUsePalette = false;
        return false;
    }

    logOutput << CurrentTimeString() << "initializing palette" << endl;

    DWORD caps;
    HRESULT hr;
    if (FAILED(hr = lpDDPalette->GetCaps(&caps)))
    {
        logOutput << CurrentTimeString() << "Failed to get palette caps" << endl;
        printDDrawError(hr, "SetupPalette");
        return false;
    }

    if (caps & DDPCAPS_8BITENTRIES)
    {
        logOutput << CurrentTimeString() << "8-bit index-palette used (lookup color is an index to another lookup table), not implemented" << endl;
        return false;
    }

    DWORD numEntries = 0;
    if (caps & DDPCAPS_8BIT)
        numEntries = 0x100;
    else if (caps & DDPCAPS_4BIT)
        numEntries = 0x10;
    else if (caps & DDPCAPS_2BIT)
        numEntries = 0x04;
    else if (caps & DDPCAPS_1BIT)
        numEntries = 0x02;
    else
    {
        logOutput << CurrentTimeString() << "Unrecognized palette format" << endl;
        return false;
    }

    //logOutput << CurrentTimeString() << "Trying to retrieve " << numEntries << " palette entries" << endl;

    g_CurrentPalette.Reallocate(numEntries);
    hr = lpDDPalette->GetEntries(0, 0, numEntries, g_CurrentPalette.entries);
    if (FAILED(hr))
    {
        logOutput << CurrentTimeString() << "Failed to retrieve palette entries" << endl;
        printDDrawError(hr, "SetupPalette");
        g_CurrentPalette.Free();
        return false;
    }

    g_CurrentPalette.primary_surface_palette_ref = lpDDPalette;
    g_CurrentPalette.bInitialized = true;
    g_bUsePalette = true;

    logOutput << CurrentTimeString() << "Initialized palette with " << numEntries << " color entries" << endl;

    return true;
}
Exemple #28
0
void CleanUpDDraw()
{
    logOutput << CurrentTimeString() << "Cleaning up" << endl;
    if (copyData)
        copyData->lastRendered = -1;

    if (hCopyThread)
    {
        bKillThread = true;
        SetEvent(hCopyEvent);
        if (WaitForSingleObject(hCopyThread, 500) != WAIT_OBJECT_0)
            TerminateThread(hCopyThread, -1);

        CloseHandle(hCopyThread);
        CloseHandle(hCopyEvent);

        hCopyThread = NULL;
        hCopyEvent = NULL;
    }

    ddrawSurfaceRelease.Unhook();
    for (int i = 0; i < NUM_BUFFERS; i++)
    {
        if (ddCaptures[i])
        {
            ddCaptures[i]->Release();
            ddCaptures[i] = NULL;
        }
    }
    ddrawSurfaceRelease.Rehook();

    DestroySharedMemory();

    bHasTextures = false;
    curCapture = 0;
    curCPUTexture = 0;
    keepAliveTime = 0;
    resetCount++;
    copyWait = 0;
    lastTime = 0;
    g_frontSurface = NULL;
    g_bUseFlipMethod = false;
    bTargetAcquired = false;
    g_dwSize = 0;
    g_bUse32bitCapture = false;
    g_bConvert16to32 = false;
    g_bUsePalette = false;
    g_dwCaptureSize = 0;

    if (g_ddInterface)
    {
        g_ddInterface->Release();
        g_ddInterface = NULL;
    }

    g_CurrentPalette.Free();

    if (g_surfaceDesc)
        delete g_surfaceDesc;
    g_surfaceDesc = NULL;

    if (ddUnlockFctMutex)
    {
        CloseHandle(ddUnlockFctMutex);
        ddUnlockFctMutex = 0;
    }

    //UnhookAll();

    logOutput << CurrentTimeString() << "---------------------- Cleared DirectDraw Capture ----------------------" << endl;
}
Exemple #29
0
void CaptureDDraw()
{
    //RUNEVERYRESET logOutput << CurrentTimeString() << "called CaptureDDraw()" << endl;

    if (bCapturing && WaitForSingleObject(hSignalEnd, 0) == WAIT_OBJECT_0)
    {
        //logOutput << CurrentTimeString() << "not capturing or received hSignalEnd" << endl;
        bStopRequested = true;
    }

    if (bCapturing && !IsWindow(hwndOBS))
    {
        //logOutput << CurrentTimeString() << "not capturing or OBS window not found" << endl;
        hwndOBS = NULL;
        bStopRequested = true;
    }

    if (bStopRequested)
    {
        CleanUpDDraw();
        bCapturing = false;
        bStopRequested = false;
    }

    if (!bCapturing && WaitForSingleObject(hSignalRestart, 0) == WAIT_OBJECT_0)
    {
        //logOutput << CurrentTimeString() << "capturing and received hSignalRestart" << endl;
        hwndOBS = FindWindow(OBS_WINDOW_CLASS, NULL);
        if (hwndOBS) {
            logOutput << CurrentTimeString() << "received restart event, capturing" << endl;
            bCapturing = true;
        }
        else {
            logOutput << CurrentTimeString() << "received restart event, but couldn't find window" << endl;
        }
    }

    LONGLONG timeVal = OSGetTimeMicroseconds();

    //check keep alive state, dumb but effective
    if (bCapturing)
    {
        if (!keepAliveTime)
            keepAliveTime = timeVal;

        if ((timeVal - keepAliveTime) > 5000000)
        {
            HANDLE hKeepAlive = OpenEvent(EVENT_ALL_ACCESS, FALSE, strKeepAlive.c_str());
            if (hKeepAlive) {
                CloseHandle(hKeepAlive);
            }
            else {
                logOutput << CurrentTimeString() << "Keepalive no longer found on ddraw, freeing capture data" << endl;
                CleanUpDDraw();
                bCapturing = false;
            }

            keepAliveTime = timeVal;
        }
    }

    if (bHasTextures)
    {
        LONGLONG frameTime;
        if (bCapturing)
        {
            if (copyData)
            {
                if (frameTime = copyData->frameTime)
                {
                    LONGLONG timeElapsed = timeVal - lastTime;

                    if (timeElapsed >= frameTime)
                    {
                        lastTime += frameTime;
                        if (timeElapsed > frameTime * 2)
                            lastTime = timeVal;


                        //logOutput << CurrentTimeString() << "CaptureDDraw: capturing screen from 0x" << g_frontSurface << endl;

                        HRESULT hr;
                        ddrawSurfaceBlt.Unhook();
                        hr = ddCaptures[curCapture]->Blt(NULL, g_frontSurface, NULL, DDBLT_ASYNC, NULL);
                        ddrawSurfaceBlt.Rehook();
                        if (SUCCEEDED(hr))
                        {
                            DWORD nextCapture = (curCapture == NUM_BUFFERS - 1) ? 0 : (curCapture + 1);
                            curCPUTexture = curCapture;
                            curCapture = nextCapture;

                            SetEvent(hCopyEvent);
                        }
                        else
                        {
                            printDDrawError(hr, "CaptureDDraw");
                        }
                        //logOutput << CurrentTimeString() << "CaptureDDraw: finished capturing" << endl;
                    }
                }
            }
        }
    }
}
Exemple #30
0
void ClearGLData()
{
    if(copyData)
        copyData->lastRendered = -1;

    if(hCopyThread)
    {
        bKillThread = true;
        SetEvent(hCopyEvent);
        if(WaitForSingleObject(hCopyThread, 500) != WAIT_OBJECT_0)
            TerminateThread(hCopyThread, -1);

        CloseHandle(hCopyThread);
        CloseHandle(hCopyEvent);

        hCopyThread = NULL;
        hCopyEvent = NULL;
    }

    for(int i=0; i<NUM_BUFFERS; i++)
    {
        if(glLockedTextures[i])
        {
            OSEnterMutex(glDataMutexes[i]);

            glBindBuffer(GL_PIXEL_PACK_BUFFER, gltextures[i]);
            glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
            glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);

            glLockedTextures[i] = false;

            OSLeaveMutex(glDataMutexes[i]);
        }
    }

    if(bHasTextures)
    {
        glDeleteBuffers(NUM_BUFFERS, gltextures);
        bHasTextures = false;

        ZeroMemory(gltextures, sizeof(gltextures));
    }

    for(int i=0; i<NUM_BUFFERS; i++)
    {
        if(glDataMutexes[i])
        {
            OSCloseMutex(glDataMutexes[i]);
            glDataMutexes[i] = NULL;
        }
    }

    DestroySharedMemory();
    copyData = NULL;
    copyWait = 0;
    lastTime = 0;
    curCapture = 0;
    curCPUTexture = 0;
    keepAliveTime = 0;
    resetCount++;
    pCopyData = NULL;

    logOutput << CurrentTimeString() << "---------------------- Cleared OpenGL Capture ----------------------" << endl;
}