diff --git a/Software/hooks/msvcstub.h b/Software/common/msvcstub.h similarity index 85% rename from Software/hooks/msvcstub.h rename to Software/common/msvcstub.h index c9c5b983..7d774091 100644 --- a/Software/hooks/msvcstub.h +++ b/Software/common/msvcstub.h @@ -1,6 +1,7 @@ #ifndef MSVCSTUB_H #define MSVCSTUB_H +#if !defined _MSC_VER #define __in #define __out #define __inout @@ -16,6 +17,8 @@ #define __out_ecount(x) #define __in_ecount_opt(x) #define __out_ecount_opt(x) +#endif // !defined _MSC_VER + #define WINAPI_INLINE WINAPI #endif // MSVCSTUB_H diff --git a/Software/grab/D3D10Grabber.cpp b/Software/grab/D3D10Grabber.cpp index 743199d7..5c912619 100644 --- a/Software/grab/D3D10Grabber.cpp +++ b/Software/grab/D3D10Grabber.cpp @@ -27,100 +27,50 @@ #ifdef D3D10_GRAB_SUPPORT -#include "../../common/D3D10GrabberDefs.hpp" -#include -#include -#include +#include #define WINAPI_INLINE WINAPI -#define DXGI_PRESENT_FUNC_ORD 8 -#define D3D9_SCPRESENT_FUNC_ORD 3 -#define D3D9_PRESENT_FUNC_ORD 17 - -#define __in -#define __out -#define __inout -#define __inout_opt -#define __in_bcount(x) -#define __out_bcount(x) -#define __out_bcount_opt(x) -#define __in_bcount_opt(x) -#define __in_opt -#define __out_opt -#define __out_ecount_part_opt(x,y) -#define __in_ecount(x) -#define __out_ecount(x) -#define __in_ecount_opt(x) -#define __out_ecount_opt(x) -#include -#include"DXGI.h" -#include"D3D10_1.h" -#include"D3D10.h" -#include "d3d9.h" -#include"../src/debug.h" -#include"math.h" + +#include #include -#include "sddl.h" -#include "psapi.h" -#include "shlwapi.h" -#include "initguid.h" +#include +#include #include "calculations.hpp" -// IID_ILibraryInjector = {029587AD-87F3-4623-941F-E37BF99A6DB2} -DEFINE_GUID(IID_ILibraryInjector , 0x029587ad, 0x87f3, 0x4623, 0x94, 0x1f, 0xe3, 0x7b, 0xf9, 0x9a, 0x6d, 0xb2); - -// CLSID_ILibraryInjector = {FC9D8F66-7B9A-47b7-8C5B-830BFF0E48C9} -DEFINE_GUID(CLSID_ILibraryInjector, 0xfc9d8f66, 0x7b9a, 0x47b7, 0x8c, 0x5b, 0x83, 0x0b, 0xff, 0x0e, 0x48, 0xc9); - -const WCHAR lightpackHooksDllName[] = L"prismatik-hooks.dll"; - -using namespace std; +#include "WinUtils.hpp" +#include "WinDXUtils.hpp" +#include"../../common/D3D10GrabberDefs.hpp" +#include "../src/debug.h" +#include "../libraryinjector/ILibraryInjector.h" -PVOID D3D10Grabber::m_memMap = NULL; -HANDLE D3D10Grabber::m_sharedMem = NULL; -HANDLE D3D10Grabber::m_mutex = NULL; -MONITORINFO D3D10Grabber::m_monitorInfo; -QTimer * D3D10Grabber::m_processesScanAndInfectTimer; -bool D3D10Grabber::m_isInited = false; -bool D3D10Grabber::m_isStarted = false; -ILibraryInjector * D3D10Grabber::m_libraryInjector = NULL; -WCHAR D3D10Grabber::m_hooksLibPath[300]; -WCHAR D3D10Grabber::m_systemrootPath[300]; -bool D3D10Grabber::m_isFrameGrabbedDuringLastSecond = false; +#include "../../common/msvcstub.h" +#include +#include -GetHwndCallback_t D3D10Grabber::m_getHwndCb = NULL; - -UINT D3D10Grabber::m_lastFrameId; - -LPWSTR pwstrExcludeProcesses[]={L"skype.exe", L"chrome.exe", L"firefox.exe"}; #define SIZEOF_ARRAY(a) (sizeof(a)/sizeof(a[0])) -/*! - We are not allowed to create DXGIFactory inside of Dll, so determine SwapChain->Present vtbl location here. - To determine location we need to create SwapChain instance and dereference pointer. - \param hWnd window handle to bind SwapChain to - \return UINT -*/ -UINT GetDxgiPresentOffset(HWND hWnd); - -UINT GetD3D9PresentOffset(HWND hWnd); -UINT GetD3D9SCPresentOffset(HWND hWnd); - -BOOL SetPrivilege(HANDLE hToken, LPCTSTR szPrivName, BOOL fEnable); - -BOOL AcquirePrivileges(); - -QList * getDxProcessesIDs(QList * processes, const WCHAR *wstrSystemRootPath); - -PVOID BuildRestrictedSD(PSECURITY_DESCRIPTOR pSD); - -// The following function frees memory allocated in the -// BuildRestrictedSD() function -VOID FreeRestrictedSD(PVOID ptr); +using namespace std; +using namespace WinUtils; + +namespace { +class D3D10GrabberWorker: public QObject { + Q_OBJECT + +public: + D3D10GrabberWorker(QObject *parent, LPSECURITY_ATTRIBUTES lpsa); + ~D3D10GrabberWorker(); +private: + HANDLE m_frameGrabbedEvent; +signals: + void frameGrabbed(); +public slots: + void runLoop(); +}; D3D10GrabberWorker::D3D10GrabberWorker(QObject *parent, LPSECURITY_ATTRIBUTES lpsa) : QObject(parent) { if (NULL == (m_frameGrabbedEvent = CreateEventW(lpsa, false, false, HOOKSGRABBER_FRAMEGRABBED_EVENT_NAME))) { qCritical() << Q_FUNC_INFO << "unable to create frameGrabbedEvent"; } } + D3D10GrabberWorker::~D3D10GrabberWorker() { if (m_frameGrabbedEvent) CloseHandle(m_frameGrabbedEvent); @@ -136,89 +86,87 @@ void D3D10GrabberWorker::runLoop() { } } } +} // namespace -bool D3D10Grabber::initIPC(LPSECURITY_ATTRIBUTES lpsa) { - - WSADATA wsaData; - int result = WSAStartup(MAKEWORD(2,2), &wsaData); - if (result != 0) { - qCritical() << Q_FUNC_INFO << "can't initialize winsocks2. error code " << result; - return false; +class D3D10GrabberImpl: public QObject +{ + Q_OBJECT + +public: + D3D10GrabberImpl(D3D10Grabber &owner, GetHwndCallback_t getHwndCb) + : m_sharedMem(NULL), + m_mutex(NULL), + m_isStarted(false), + m_memMap(NULL), + m_lastFrameId(0), + m_isInited(false), + m_libraryInjector(NULL), + m_isFrameGrabbedDuringLastSecond(false), + m_getHwndCb(getHwndCb), + m_owner(owner) + {} + + ~D3D10GrabberImpl() + { + shutdown(); } - sockaddr_in localhost; - in_addr adr; - - m_sharedMem = CreateFileMappingW(INVALID_HANDLE_VALUE, lpsa, PAGE_READWRITE, 0, HOOKSGRABBER_SHARED_MEM_SIZE, HOOKSGRABBER_SHARED_MEM_NAME ); - if(!m_sharedMem) { - m_sharedMem = OpenFileMappingW(GENERIC_READ | GENERIC_WRITE, false, HOOKSGRABBER_SHARED_MEM_NAME); - if(!m_sharedMem) { - qCritical() << Q_FUNC_INFO << "couldn't create memory mapped file. error code " << GetLastError(); + bool initIPC(LPSECURITY_ATTRIBUTES lpsa) { + WSADATA wsaData; + int result = WSAStartup(MAKEWORD(2,2), &wsaData); + if (result != 0) { + qCritical() << Q_FUNC_INFO << "can't initialize winsocks2. error code " << result; return false; } - } - m_memMap = MapViewOfFile(m_sharedMem, FILE_MAP_READ, 0, 0, HOOKSGRABBER_SHARED_MEM_SIZE ); - if(!m_memMap) { - qCritical() << Q_FUNC_INFO << "couldn't create map view. error code " << GetLastError(); - freeIPC(); - return false; - } - - PVOID memMap = MapViewOfFile(m_sharedMem, FILE_MAP_WRITE, 0, 0, HOOKSGRABBER_SHARED_MEM_SIZE ); - if(!memMap) { - qWarning() << Q_FUNC_INFO << "couldn't clear shared memory. error code " << GetLastError(); - } else { - memset(&m_memDesc, 0, sizeof(m_memDesc)); - m_memDesc.frameId = HOOKSGRABBER_BLANK_FRAME_ID; - - m_memDesc.d3d9PresentFuncOffset = GetD3D9PresentOffset(m_getHwndCb()); - m_memDesc.d3d9SCPresentFuncOffset = GetD3D9SCPresentOffset(m_getHwndCb()); - m_memDesc.dxgiPresentFuncOffset = GetDxgiPresentOffset(m_getHwndCb()); + if (!initSharedMemory(lpsa)) + return false; - //converting logLevel from our app's level to EventLog's level - m_memDesc.logLevel = Debug::HighLevel - g_debugLevel; + if(!mapFile()) { + qCritical() << Q_FUNC_INFO << "couldn't create map view. error code " << GetLastError(); + freeIPC(); + return false; + } - memcpy(memMap, &m_memDesc, sizeof(m_memDesc)); - UnmapViewOfFile(memMap); - } + HOOKSGRABBER_SHARED_MEM_DESC memDesc; + memset(&memDesc, 0, sizeof(HOOKSGRABBER_SHARED_MEM_DESC)); + if (fillMemoryDesc(&memDesc) && copyMemDesc(memDesc)) { + memcpy(&m_memDesc, &memDesc, sizeof(HOOKSGRABBER_SHARED_MEM_DESC)); + } else { + qWarning() << Q_FUNC_INFO << "couldn't write SHARED_MEM_DESC to shared memory!"; + } - m_mutex = CreateMutexW(lpsa, false, HOOKSGRABBER_MUTEX_MEM_NAME); - if(!m_mutex) { - m_mutex = OpenMutexW(SYNCHRONIZE, false, HOOKSGRABBER_MUTEX_MEM_NAME); - if(!m_mutex) { - qCritical() << Q_FUNC_INFO << "couldn't create mutex. error code " << GetLastError(); + if(!createMutex(lpsa)) { + qCritical() << Q_FUNC_INFO << "couldn't create mutex."; freeIPC(); return false; } - } - return true; -} + return true; + } -D3D10Grabber::D3D10Grabber(QObject *parent, QList *grabResult, QList *grabWidgets, GetHwndCallback_t getHwndCb) : GrabberBase(parent, grabResult, grabWidgets) { - m_getHwndCb = getHwndCb; -} + bool init() { + if(m_isInited) + return true; -void D3D10Grabber::init(void) { - HRESULT hr; - if(!m_isInited) { AcquirePrivileges(); - GetCurrentDirectoryW(sizeof(m_hooksLibPath)/2, m_hooksLibPath); + GetCurrentDirectoryW(SIZEOF_ARRAY(m_hooksLibPath), m_hooksLibPath); wcscat(m_hooksLibPath, L"\\"); wcscat(m_hooksLibPath, lightpackHooksDllName); - GetWindowsDirectoryW(m_systemrootPath, sizeof(m_systemrootPath)); + GetWindowsDirectoryW(m_systemrootPath, SIZEOF_ARRAY(m_systemrootPath)); - hr = CoInitialize(0); + HRESULT hr = CoInitialize(0); // hr = InitComSecurity(); // hr = CoCreateInstanceAsAdmin(NULL, CLSID_ILibraryInjector, IID_ILibraryInjector, reinterpret_cast(&m_libraryInjector)); hr = CoCreateInstance(CLSID_ILibraryInjector, NULL, CLSCTX_INPROC_SERVER, IID_ILibraryInjector, reinterpret_cast(&m_libraryInjector)); if (FAILED(hr)) { qCritical() << Q_FUNC_INFO << "Can't create libraryinjector. D3D10Grabber wasn't initialised. Please try to register server: regsvr32 libraryinjector.dll"; - return; + return false; } +#if 0 + // TODO: Remove this code or use |sa| in initIPC() SECURITY_ATTRIBUTES sa; SECURITY_DESCRIPTOR sd; @@ -234,650 +182,358 @@ void D3D10Grabber::init(void) { sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = &sd; sa.bInheritHandle = FALSE; +#endif if (!initIPC(NULL)) { freeIPC(); qCritical() << Q_FUNC_INFO << "Can't init interprocess communication mechanism. D3D10Grabber wasn't initialised."; - return; + return false; } - m_processesScanAndInfectTimer = new QTimer(this); + +#if 0 + FreeRestrictedSD(ptr); +#endif + m_processesScanAndInfectTimer.reset(new QTimer(this)); m_processesScanAndInfectTimer->setInterval(5000); m_processesScanAndInfectTimer->setSingleShot(false); - connect(m_processesScanAndInfectTimer, SIGNAL(timeout()), this, SLOT(infectCleanDxProcesses()) ); + connect(m_processesScanAndInfectTimer.data(), SIGNAL(timeout()), this, SLOT(infectCleanDxProcesses()) ); m_processesScanAndInfectTimer->start(); - m_workerThread = new QThread(); - m_worker = new D3D10GrabberWorker(NULL, NULL); - m_worker->moveToThread(m_workerThread); + m_workerThread.reset(new QThread()); + m_worker.reset(new D3D10GrabberWorker(NULL, NULL)); + m_worker->moveToThread(m_workerThread.data()); m_workerThread->start(); - connect(m_worker, SIGNAL(frameGrabbed()), this, SLOT(grab())); - QMetaObject::invokeMethod(m_worker, "runLoop", Qt::QueuedConnection); + connect(m_worker.data(), SIGNAL(frameGrabbed()), this, SLOT(grab())); + QMetaObject::invokeMethod(m_worker.data(), "runLoop", Qt::QueuedConnection); - FreeRestrictedSD(ptr); - - m_checkIfFrameGrabbedTimer = new QTimer(); + m_checkIfFrameGrabbedTimer.reset(new QTimer()); m_checkIfFrameGrabbedTimer->setSingleShot(false); m_checkIfFrameGrabbedTimer->setInterval(1000); - connect(m_checkIfFrameGrabbedTimer, SIGNAL(timeout()), SLOT(handleIfFrameGrabbed())); + connect(m_checkIfFrameGrabbedTimer.data(), SIGNAL(timeout()), SLOT(handleIfFrameGrabbed())); m_checkIfFrameGrabbedTimer->start(); - m_isInited = true; - - + return m_isInited; } -} -void D3D10Grabber::startGrabbing() { - DEBUG_LOW_LEVEL << Q_FUNC_INFO << this->metaObject()->className(); - m_isStarted = true; -} - -void D3D10Grabber::stopGrabbing() { - DEBUG_LOW_LEVEL << Q_FUNC_INFO << this->metaObject()->className(); - m_isStarted = false; -} - -void D3D10Grabber::setGrabInterval(int msec) { - DEBUG_LOW_LEVEL << Q_FUNC_INFO << this->metaObject()->className(); - Q_UNUSED(msec); -} + void start() { m_isStarted = true; } + void stop() { m_isStarted = false; } + bool isStarted() { return m_isStarted; } -void D3D10Grabber::grab() { - DEBUG_HIGH_LEVEL << Q_FUNC_INFO << this->metaObject()->className(); - if (m_isStarted) { - m_lastGrabResult = _grab(); - emit frameGrabAttempted(m_lastGrabResult); - } else { - emit grabberStateChangeRequested(true); - } -} + GrabResult grab(QList *grabResult, QList *grabWidgets) + { + if (!m_isInited) { + return GrabResultFrameNotReady; + } -GrabResult D3D10Grabber::_grab() { - DEBUG_HIGH_LEVEL << Q_FUNC_INFO << this->metaObject()->className(); - if (!m_isInited) { - return GrabResultFrameNotReady; - } - GrabResult result; - memcpy(&m_memDesc, m_memMap, sizeof(m_memDesc)); - if( m_memDesc.frameId != HOOKSGRABBER_BLANK_FRAME_ID) { - if( m_memDesc.frameId != m_lastFrameId) { - m_lastFrameId = m_memDesc.frameId; - m_grabResult->clear(); - foreach(GrabWidget *widget, *m_grabWidgets) { - if(widget->isAreaEnabled()) { - QRect widgetRect = widget->frameGeometry(); - m_grabResult->append(getColor(widgetRect)); - } else { - m_grabResult->append(qRgb(0,0,0)); + GrabResult result; + memcpy(&m_memDesc, m_memMap, sizeof(m_memDesc)); + if( m_memDesc.frameId != HOOKSGRABBER_BLANK_FRAME_ID) { + if( m_memDesc.frameId != m_lastFrameId) { + m_lastFrameId = m_memDesc.frameId; + grabResult->clear(); + foreach(GrabWidget *widget, *grabWidgets) { + if(widget->isAreaEnabled()) { + grabResult->append(getColor(widget->frameGeometry())); + } else { + grabResult->append(qRgb(0,0,0)); + } } - } - m_isFrameGrabbedDuringLastSecond = true; - result = GrabResultOk; + m_isFrameGrabbedDuringLastSecond = true; + result = GrabResultOk; + } else { + result = GrabResultFrameNotReady; + } } else { result = GrabResultFrameNotReady; } - } else { - result = GrabResultFrameNotReady; - } - return result; -} - -void D3D10Grabber::handleIfFrameGrabbed() { - if (!m_isFrameGrabbedDuringLastSecond) { - if (m_isStarted) { - emit grabberStateChangeRequested(false); - } - } else { - m_isFrameGrabbedDuringLastSecond = false; + return result; } -} -D3D10Grabber::~D3D10Grabber() { - if(m_isInited) { - if (m_libraryInjector) - m_libraryInjector->Release(); - CoUninitialize(); - freeIPC(); - m_isInited = false; - disconnect(this, SLOT(handleIfFrameGrabbed())); - delete m_worker; - delete m_workerThread; - delete m_checkIfFrameGrabbedTimer; - } -} + void updateGrabMonitor(QWidget *widget) + { + if (m_isInited) { + HMONITOR hMonitor = MonitorFromWindow( reinterpret_cast(widget->winId()), MONITOR_DEFAULTTONEAREST ); -void D3D10Grabber::freeIPC() { - if(m_memMap) { - UnmapViewOfFile(m_memMap); - } + ZeroMemory( &m_monitorInfo, sizeof(MONITORINFO) ); + m_monitorInfo.cbSize = sizeof(MONITORINFO); - if(m_sharedMem) { - CloseHandle(m_sharedMem); + // Get position and resolution of the monitor + GetMonitorInfo( hMonitor, &m_monitorInfo ); + } } - if(m_mutex) { - CloseHandle(m_mutex); +private slots: + void infectCleanDxProcesses(void) { + if (m_isInited && m_libraryInjector) { + QList processes = QList(); + getDxProcessesIDs(&processes, m_systemrootPath); + foreach (DWORD procId, processes) { + m_libraryInjector->Inject(procId, m_hooksLibPath); + } + } } -} -void D3D10Grabber::updateGrabMonitor(QWidget *widget) { - DEBUG_LOW_LEVEL << Q_FUNC_INFO << this->metaObject()->className(); - if (m_isInited) { - HMONITOR hMonitor = MonitorFromWindow( reinterpret_cast(widget->winId()), MONITOR_DEFAULTTONEAREST ); - - ZeroMemory( &m_monitorInfo, sizeof(MONITORINFO) ); - m_monitorInfo.cbSize = sizeof(MONITORINFO); - - // Get position and resolution of the monitor - GetMonitorInfo( hMonitor, &m_monitorInfo ); - -// m_fallbackGrabber->updateGrabMonitor(widget); + void handleIfFrameGrabbed() { + if (!m_isFrameGrabbedDuringLastSecond) { + if (m_isStarted) { + emit m_owner.grabberStateChangeRequested(false); + } + } else { + m_isFrameGrabbedDuringLastSecond = false; + } } -} -//void D3D10Grabber::setFallbackGrabber(GrabberBase *grabber) { -// m_fallbackGrabber = grabber; -//} +private: + QRgb getColor(const QRect &widgetRect) + { + DEBUG_HIGH_LEVEL << Q_FUNC_INFO << Debug::toString(widgetRect); -void D3D10Grabber::infectCleanDxProcesses() { - if (m_isInited) { - QList processes = QList(); - getDxProcessesIDs(&processes, m_systemrootPath); - foreach (DWORD procId, processes) { - m_libraryInjector->Inject(procId, m_hooksLibPath); + if (m_memMap == NULL) + { + qCritical() << Q_FUNC_INFO << "m_memMap == NULL"; + return 0; } - } -} -UINT GetDxgiPresentOffset(HWND hwnd) { - Q_ASSERT(hwnd != NULL); - IDXGIFactory1 * factory = NULL; - IDXGIAdapter * adapter; - HRESULT hresult = CreateDXGIFactory(IID_IDXGIFactory, reinterpret_cast(&factory)); - if (hresult != S_OK) { - qCritical() << "Can't create DXGIFactory. " << hresult; - return NULL; - } - hresult = factory->EnumAdapters(0, &adapter); - if (hresult != S_OK) { - qCritical() << "Can't enumerate adapters. " << hresult; - return NULL; - } + unsigned char * pbPixelsBuff = reinterpret_cast(m_memMap) + sizeof(HOOKSGRABBER_SHARED_MEM_DESC); + RECT rcMonitor = m_monitorInfo.rcMonitor; + QRect monitorRect = QRect( QPoint(rcMonitor.left, rcMonitor.top), QSize(m_memDesc.width, m_memDesc.height)); - DXGI_MODE_DESC dxgiModeDesc; - dxgiModeDesc.Width = 1; - dxgiModeDesc.Height = 1; - dxgiModeDesc.RefreshRate.Numerator = 1; - dxgiModeDesc.RefreshRate.Denominator = 1; - dxgiModeDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - dxgiModeDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE; - dxgiModeDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; - - DXGI_SAMPLE_DESC dxgiSampleDesc = {1, 0}; - - DXGI_SWAP_CHAIN_DESC dxgiSwapChainDesc; - memset(&dxgiSwapChainDesc, 0, sizeof(DXGI_SWAP_CHAIN_DESC)); - dxgiSwapChainDesc.BufferDesc = dxgiModeDesc; - dxgiSwapChainDesc.SampleDesc = dxgiSampleDesc; - dxgiSwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - dxgiSwapChainDesc.BufferCount = 2; - dxgiSwapChainDesc.OutputWindow = hwnd; - dxgiSwapChainDesc.Windowed = true; - dxgiSwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; - dxgiSwapChainDesc.Flags = 0; - - IDXGISwapChain * pSc; - ID3D10Device * pDev; - hresult = D3D10CreateDeviceAndSwapChain(adapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, 0, D3D10_SDK_VERSION, &dxgiSwapChainDesc, &pSc, &pDev); - if (S_OK != hresult) { - qCritical() << Q_FUNC_INFO << QString("Can't create D3D10Device and SwapChain. hresult = 0x%1").arg(QString::number(hresult, 16)); - return NULL; - } + QRect clippedRect = monitorRect.intersected(widgetRect); + // Checking for the 'grabme' widget position inside the monitor that is used to capture color + if( !clippedRect.isValid() ){ - uintptr_t * pvtbl = reinterpret_cast(pSc); - uintptr_t presentFuncPtr = *pvtbl + sizeof(void *)*DXGI_PRESENT_FUNC_ORD; + DEBUG_MID_LEVEL << "Widget 'grabme' is out of screen:" << Debug::toString(clippedRect); - char buf[100]; - sprintf(buf, "presentFuncPtr=%x", presentFuncPtr); - DEBUG_LOW_LEVEL << Q_FUNC_INFO << buf; - - intptr_t hDxgi = reinterpret_cast(GetModuleHandle(L"dxgi.dll")); - int presentFuncOffset = static_cast(presentFuncPtr - hDxgi); + // Widget 'grabme' is out of screen + return 0x000000; + } - sprintf(buf, "presentFuncOffset=%x", presentFuncOffset); - DEBUG_LOW_LEVEL << Q_FUNC_INFO << buf; + // Convert coordinates from "Main" desktop coord-system to capture-monitor coord-system + QRect preparedRect = clippedRect.translated(-monitorRect.x(), -monitorRect.y()); + // Align width by 4 for accelerated calculations + preparedRect.setWidth(preparedRect.width() - (preparedRect.width() % 4)); - pSc->Release(); - pDev->Release(); - adapter->Release(); - factory->Release(); + if( !preparedRect.isValid() ){ + qWarning() << Q_FUNC_INFO << " preparedRect is not valid:" << Debug::toString(preparedRect); - return presentFuncOffset; -} + // width and height can't be negative + return 0x000000; + } -typedef IDirect3D9 * WINAPI (*Direct3DCreate9Func)(UINT SDKVersion); -UINT GetD3D9PresentOffset(HWND hWnd){ - IDirect3D9 *pD3D = NULL; - HINSTANCE hD3d9 = LoadLibrary(L"d3d9.dll"); - Direct3DCreate9Func createDev = reinterpret_cast(GetProcAddress(hD3d9, "Direct3DCreate9")); - pD3D = createDev(D3D_SDK_VERSION); - if ( !pD3D) - { - qCritical() << "Test_DirectX9 Direct3DCreate9(%d) call FAILED" << D3D_SDK_VERSION ; - return NULL; - } + QRgb result; - // step 3: Get IDirect3DDevice9 - D3DDISPLAYMODE d3ddm; - HRESULT hRes = pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm ); - if (FAILED(hRes)) - { - qCritical() << QString("Test_DirectX9 GetAdapterDisplayMode failed. 0x%x").arg( hRes); - return NULL; - } + if (Grab::Calculations::calculateAvgColor(&result, pbPixelsBuff, m_memDesc.format, m_memDesc.rowPitch, preparedRect) == 0) { + return result; + } else { + return qRgb(0,0,0); + } - D3DPRESENT_PARAMETERS d3dpp; - ZeroMemory( &d3dpp, sizeof(d3dpp)); - d3dpp.Windowed = true; - d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; - d3dpp.BackBufferFormat = d3ddm.Format; - - IDirect3DDevice9 *pD3DDevice; - hRes = pD3D->CreateDevice( - D3DADAPTER_DEFAULT, - D3DDEVTYPE_HAL, // the device we suppose any app would be using. - hWnd, - D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_DISABLE_DRIVER_MANAGEMENT, - &d3dpp, &pD3DDevice); - if (FAILED(hRes)) - { - qCritical() << QString("Test_DirectX9 CreateDevice failed. 0x%x").arg(hRes); - return NULL; + #if 0 + if (screenWidth < 1920 && (r > 120 || g > 120 || b > 120)) { + int monitorWidth = screenWidth; + int monitorHeight = screenHeight; + const int BytesPerPixel = 4; + // Save image of screen: + QImage * im = new QImage( monitorWidth, monitorHeight, QImage::Format_RGB32 ); + for(int i=0; isetPixel(i, j, rgb); + } + } + im->save("screen.jpg"); + delete im; + } + #endif } - IDirect3DSwapChain9 *pD3DSwapChain; - hRes = pD3DDevice->GetSwapChain( 0, &pD3DSwapChain); - if (FAILED(hRes)) - { - qCritical() << QString("Test_DirectX9 GetSwapChain failed. 0x%x").arg(hRes); - return NULL; - } - else + void freeIPC() { - uintptr_t * pvtbl = *((uintptr_t**)(pD3DDevice)); - uintptr_t presentFuncPtr = pvtbl[D3D9_PRESENT_FUNC_ORD]; - char buf[100]; - sprintf(buf, "presentFuncPtr=%x", presentFuncPtr); - DEBUG_LOW_LEVEL << Q_FUNC_INFO << buf; - - UINT presentFuncOffset = (presentFuncPtr - reinterpret_cast(hD3d9)); - - sprintf(buf, "presentFuncOffset=%x", presentFuncOffset); - DEBUG_LOW_LEVEL << Q_FUNC_INFO << buf; - - - pD3DSwapChain->Release(); - pD3DDevice->Release(); - pD3D->Release(); + if(m_memMap) { + UnmapViewOfFile(m_memMap); + } - return presentFuncOffset; - } -} + if(m_sharedMem) { + CloseHandle(m_sharedMem); + } -UINT GetD3D9SCPresentOffset(HWND hWnd){ - IDirect3D9 *pD3D = NULL; - HINSTANCE hD3d9 = LoadLibrary(L"d3d9.dll"); - Direct3DCreate9Func createDev = reinterpret_cast(GetProcAddress(hD3d9, "Direct3DCreate9")); - pD3D = createDev(D3D_SDK_VERSION); - if ( !pD3D) - { - qCritical() << "Test_DirectX9 Direct3DCreate9(%d) call FAILED" << D3D_SDK_VERSION ; - return NULL; + if(m_mutex) { + CloseHandle(m_mutex); + } } - // step 3: Get IDirect3DDevice9 - D3DDISPLAYMODE d3ddm; - HRESULT hRes = pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm ); - if (FAILED(hRes)) + bool initSharedMemory(LPSECURITY_ATTRIBUTES lpsa) { - qCritical() << QString("Test_DirectX9 GetAdapterDisplayMode failed. 0x%x").arg( hRes); - return NULL; - } + m_sharedMem = CreateFileMappingW(INVALID_HANDLE_VALUE, lpsa, PAGE_READWRITE, 0, HOOKSGRABBER_SHARED_MEM_SIZE, HOOKSGRABBER_SHARED_MEM_NAME ); + if(!m_sharedMem) { + m_sharedMem = OpenFileMappingW(GENERIC_READ | GENERIC_WRITE, false, HOOKSGRABBER_SHARED_MEM_NAME); + if(!m_sharedMem) { + qCritical() << Q_FUNC_INFO << "couldn't create memory mapped file. error code " << GetLastError(); + } + } - D3DPRESENT_PARAMETERS d3dpp; - ZeroMemory( &d3dpp, sizeof(d3dpp)); - d3dpp.Windowed = true; - d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; - d3dpp.BackBufferFormat = d3ddm.Format; - - IDirect3DDevice9 *pD3DDevice; - hRes = pD3D->CreateDevice( - D3DADAPTER_DEFAULT, - D3DDEVTYPE_HAL, // the device we suppose any app would be using. - hWnd, - D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_DISABLE_DRIVER_MANAGEMENT, - &d3dpp, &pD3DDevice); - if (FAILED(hRes)) - { - qCritical() << QString("Test_DirectX9 CreateDevice failed. 0x%x").arg(hRes); - return NULL; + return NULL != m_sharedMem; } - IDirect3DSwapChain9 *pD3DSwapChain; - hRes = pD3DDevice->GetSwapChain( 0, &pD3DSwapChain); - if (FAILED(hRes)) + bool mapFile() { - qCritical() << QString("Test_DirectX9 GetSwapChain failed. 0x%x").arg(hRes); - return NULL; - } - else - { - uintptr_t * pvtbl = *((uintptr_t**)(pD3DSwapChain)); - uintptr_t presentFuncPtr = pvtbl[D3D9_SCPRESENT_FUNC_ORD]; - char buf[100]; - sprintf(buf, "presentFuncPtr=%x", presentFuncPtr); - DEBUG_LOW_LEVEL << Q_FUNC_INFO << buf; - - void *pD3d9 = reinterpret_cast(hD3d9); - UINT presentFuncOffset = (presentFuncPtr - reinterpret_cast(pD3d9)); - - sprintf(buf, "presentFuncOffset=%x", presentFuncOffset); - DEBUG_LOW_LEVEL << Q_FUNC_INFO << buf; - + if (!m_sharedMem) + return false; - pD3DSwapChain->Release(); - pD3DDevice->Release(); - pD3D->Release(); + m_memMap = MapViewOfFile(m_sharedMem, FILE_MAP_READ, 0, 0, HOOKSGRABBER_SHARED_MEM_SIZE ); + if (!m_memMap) + qWarning() << Q_FUNC_INFO << "couldn't map shared memory. error code " << GetLastError(); - return presentFuncOffset; + return NULL != m_memMap; } -} - -QRgb D3D10Grabber::getColor(QRect &widgetRect) -{ - DEBUG_HIGH_LEVEL << Q_FUNC_INFO << Debug::toString(widgetRect); - - unsigned char * pbPixelsBuff = reinterpret_cast(m_memMap) + sizeof(HOOKSGRABBER_SHARED_MEM_DESC); - - if (pbPixelsBuff == NULL) + bool fillMemoryDesc(HOOKSGRABBER_SHARED_MEM_DESC *memDesc) { - qCritical() << Q_FUNC_INFO << "pbPixelsBuff == NULL"; - return 0; - } - - RECT rcMonitor = m_monitorInfo.rcMonitor; - QRect monitorRect = QRect( QPoint(rcMonitor.left, rcMonitor.top), QSize(m_memDesc.width, m_memDesc.height)); - - QRect clippedRect = monitorRect.intersected(widgetRect); + if (!m_getHwndCb) { + qWarning() << Q_FUNC_INFO << "m_getHwndCb is NULL!"; + return false; + } - // Checking for the 'grabme' widget position inside the monitor that is used to capture color - if( !clippedRect.isValid() ){ + memDesc->frameId = HOOKSGRABBER_BLANK_FRAME_ID; - DEBUG_MID_LEVEL << "Widget 'grabme' is out of screen:" << Debug::toString(clippedRect); + HWND wnd = (HWND)m_getHwndCb(); + memDesc->d3d9PresentFuncOffset = GetD3D9PresentOffset(wnd); + memDesc->d3d9SCPresentFuncOffset = GetD3D9SCPresentOffset(wnd); + memDesc->dxgiPresentFuncOffset = GetDxgiPresentOffset(wnd); - // Widget 'grabme' is out of screen - return 0x000000; + //converting logLevel from our app's level to EventLog's level + memDesc->logLevel = Debug::HighLevel - g_debugLevel; + return true; } - // Convert coordinates from "Main" desktop coord-system to capture-monitor coord-system - QRect preparedRect = clippedRect.translated(-monitorRect.x(), -monitorRect.y()); - - // Align width by 4 for accelerated calculations - preparedRect.setWidth(preparedRect.width() - (preparedRect.width() % 4)); - - if( !preparedRect.isValid() ){ - qWarning() << Q_FUNC_INFO << " preparedRect is not valid:" << Debug::toString(preparedRect); - - // width and height can't be negative - return 0x000000; - } + bool copyMemDesc(const HOOKSGRABBER_SHARED_MEM_DESC &memDesc) const + { + if (!m_sharedMem) + return false; - QRgb result; + PVOID memMap = MapViewOfFile(m_sharedMem, FILE_MAP_WRITE, 0, 0, HOOKSGRABBER_SHARED_MEM_SIZE ); + if(!memMap) { + qWarning() << Q_FUNC_INFO << "couldn't clear shared memory. error code " << GetLastError(); + } else { + memcpy(memMap, &memDesc, sizeof(m_memDesc)); + UnmapViewOfFile(memMap); + } - if (Grab::Calculations::calculateAvgColor(&result, pbPixelsBuff, m_memDesc.format, m_memDesc.rowPitch, preparedRect) == 0) { - return result; - } else { - return qRgb(0,0,0); + return NULL != memMap; } -#if 0 - if (screenWidth < 1920 && (r > 120 || g > 120 || b > 120)) { - int monitorWidth = screenWidth; - int monitorHeight = screenHeight; - const int BytesPerPixel = 4; - // Save image of screen: - QImage * im = new QImage( monitorWidth, monitorHeight, QImage::Format_RGB32 ); - for(int i=0; isetPixel(i, j, rgb); + bool createMutex(LPSECURITY_ATTRIBUTES lpsa) + { + m_mutex = CreateMutexW(lpsa, FALSE, HOOKSGRABBER_MUTEX_MEM_NAME); + if(!m_mutex) { + m_mutex = OpenMutexW(SYNCHRONIZE, FALSE, HOOKSGRABBER_MUTEX_MEM_NAME); + if(!m_mutex) { + qCritical() << Q_FUNC_INFO << "couldn't create mutex. error code " << GetLastError(); } } - im->save("screen.jpg"); - delete im; - } -#endif -} - -BOOL SetPrivilege(HANDLE hToken, LPCTSTR szPrivName, BOOL fEnable) { - - TOKEN_PRIVILEGES tp; - tp.PrivilegeCount = 1; - LookupPrivilegeValue(NULL, szPrivName, &tp.Privileges[0].Luid); - tp.Privileges[0].Attributes = fEnable ? SE_PRIVILEGE_ENABLED : 0; - AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof (tp), NULL, NULL); - return ((GetLastError() == ERROR_SUCCESS)); - -} - -BOOL AcquirePrivileges() { - HANDLE hCurrentProc = GetCurrentProcess(); - HANDLE hCurrentProcToken; - - if (!OpenProcessToken(hCurrentProc, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hCurrentProcToken)) { -// syslog(LOG_ERR, "OpenProcessToken Error %u", GetLastError()); - } else { - if (!SetPrivilege(hCurrentProcToken, SE_DEBUG_NAME, TRUE)) { -// syslog(LOG_ERR, "SetPrivleges SE_DEBUG_NAME Error %u", GetLastError()); - } else { - return TRUE; - } + return NULL != m_mutex; } - return FALSE; -} - -QList * getDxProcessesIDs(QList * processes, const WCHAR *wstrSystemRootPath) { - - DWORD aProcesses[1024]; - HMODULE hMods[1024]; - DWORD cbNeeded; - DWORD cProcesses; - char debug_buf[255]; - WCHAR executableName[MAX_PATH]; - unsigned int i; - - // Get the list of process identifiers. - processes->clear(); - if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) ) - return NULL; - - // Calculate how many process identifiers were returned. - - cProcesses = cbNeeded / sizeof(DWORD); - - // Print the names of the modules for each process. - - for ( i = 0; i < cProcesses; i++ ) + void shutdown() { - if (aProcesses[i] != GetCurrentProcessId()) { - HANDLE hProcess; - hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | - PROCESS_VM_READ, - FALSE, aProcesses[i] ); - if (NULL == hProcess) - goto nextProcess; - - GetModuleFileNameExW(hProcess, 0, executableName, sizeof (executableName)); - - if (wcsstr(executableName, wstrSystemRootPath) != NULL) { - goto nextProcess; - } - - PathStripPathW(executableName); - - ::WideCharToMultiByte(CP_ACP, 0, executableName, -1, debug_buf, 255, NULL, NULL); - DEBUG_MID_LEVEL << Q_FUNC_INFO << debug_buf; - - for (int k=0; k < SIZEOF_ARRAY(pwstrExcludeProcesses); k++) { - if (wcsicmp(executableName, pwstrExcludeProcesses[k])== 0) { - DEBUG_MID_LEVEL << Q_FUNC_INFO << "skipping " << pwstrExcludeProcesses; - goto nextProcess; - } - } - - // Get a list of all the modules in this process. - - if( EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) - { - bool isDXPresent = false; - for ( int j = 0; j < (cbNeeded / sizeof(HMODULE)); j++ ) - { - TCHAR szModName[MAX_PATH]; - - if ( GetModuleFileNameEx( hProcess, hMods[j], szModName, - sizeof(szModName) / sizeof(TCHAR))) - { - - PathStripPathW(szModName); - ::WideCharToMultiByte(CP_ACP, 0, szModName, -1, debug_buf, 255, NULL, NULL); - DEBUG_HIGH_LEVEL << Q_FUNC_INFO << debug_buf; - - if(wcsicmp(szModName, lightpackHooksDllName) == 0) { - goto nextProcess; - } else { - if (wcsicmp(szModName, L"d3d9.dll") == 0 || - wcsicmp(szModName, L"dxgi.dll") == 0 ) - isDXPresent = true; - } - } - } - if (isDXPresent) - processes->append(aProcesses[i]); + if (!m_isInited) + return; - } -nextProcess: - // Release the handle to the process. - CloseHandle( hProcess ); - } + disconnect(this, SLOT(handleIfFrameGrabbed())); + if (m_libraryInjector) + m_libraryInjector->Release(); + freeIPC(); + CoUninitialize(); + m_isInited = false; } - return processes; + HANDLE m_sharedMem; + HANDLE m_mutex; + bool m_isStarted; + PVOID m_memMap; + UINT m_lastFrameId; + MONITORINFO m_monitorInfo; + QScopedPointer m_processesScanAndInfectTimer; + bool m_isInited; + ILibraryInjector * m_libraryInjector; + WCHAR m_hooksLibPath[300]; + WCHAR m_systemrootPath[300]; + bool m_isFrameGrabbedDuringLastSecond; + GetHwndCallback_t m_getHwndCb; + + QScopedPointer m_checkIfFrameGrabbedTimer; + QScopedPointer m_worker; + QScopedPointer m_workerThread; + HOOKSGRABBER_SHARED_MEM_DESC m_memDesc; + D3D10Grabber &m_owner; +}; + +// This will force qmake and moc to process internal classes in this file. +#include "D3D10Grabber.moc" + +D3D10Grabber::D3D10Grabber(QObject *parent, QList *grabResult, QList *grabWidgets, GetHwndCallback_t getHwndCb) + : GrabberBase(parent, grabResult, grabWidgets) { + m_impl.reset(new D3D10GrabberImpl(*this, getHwndCb)); } -PVOID BuildRestrictedSD(PSECURITY_DESCRIPTOR pSD) { - - DWORD dwAclLength; - - PSID pAuthenticatedUsersSID = NULL; - - PACL pDACL = NULL; - BOOL bResult = FALSE; - - PACCESS_ALLOWED_ACE pACE = NULL; - SID_IDENTIFIER_AUTHORITY siaNT = SECURITY_NT_AUTHORITY; - - SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; - - // initialize the security descriptor - if (!InitializeSecurityDescriptor(pSD, - SECURITY_DESCRIPTOR_REVISION)) { -// syslog(LOG_ERR, "InitializeSecurityDescriptor() failed with error %d\n", -// GetLastError()); - goto end; - } - - // obtain a sid for the Authenticated Users Group - if (!AllocateAndInitializeSid(&siaNT, 1, - SECURITY_AUTHENTICATED_USER_RID, 0, 0, 0, 0, 0, 0, 0, - &pAuthenticatedUsersSID)) { -// syslog(LOG_ERR, "AllocateAndInitializeSid() failed with error %d\n", -// GetLastError()); - goto end; - } - - // NOTE: - // - // The Authenticated Users group includes all user accounts that - // have been successfully authenticated by the system. If access - // must be restricted to a specific user or group other than - // Authenticated Users, the SID can be constructed using the - // LookupAccountSid() API based on a user or group name. - - // calculate the DACL length - dwAclLength = sizeof(ACL) - // add space for Authenticated Users group ACE - + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) - + GetLengthSid(pAuthenticatedUsersSID); - - // allocate memory for the DACL - pDACL = (PACL) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - dwAclLength); - if (!pDACL) { -// syslog(LOG_ERR, "HeapAlloc() failed with error %d\n", GetLastError()); - goto end; - } +void D3D10Grabber::init(void) { + m_impl->init(); +} - // initialize the DACL - if (!InitializeAcl(pDACL, dwAclLength, ACL_REVISION)) { -// syslog(LOG_ERR, "InitializeAcl() failed with error %d\n", -// GetLastError()); - goto end; - } +void D3D10Grabber::startGrabbing() { + DEBUG_LOW_LEVEL << Q_FUNC_INFO << this->metaObject()->className(); + m_impl->start(); +} - // add the Authenticated Users group ACE to the DACL with - // GENERIC_READ, GENERIC_WRITE, and GENERIC_EXECUTE access +void D3D10Grabber::stopGrabbing() { + DEBUG_LOW_LEVEL << Q_FUNC_INFO << this->metaObject()->className(); + m_impl->stop(); +} - if (!AddAccessAllowedAce(pDACL, ACL_REVISION, - MAXIMUM_ALLOWED , - pAuthenticatedUsersSID)) { -// syslog(LOG_ERR, "AddAccessAllowedAce() failed with error %d\n", -// GetLastError()); - goto end; - } +void D3D10Grabber::setGrabInterval(int msec) { + DEBUG_LOW_LEVEL << Q_FUNC_INFO << this->metaObject()->className(); + Q_UNUSED(msec); +} - // set the DACL in the security descriptor - if (!SetSecurityDescriptorDacl(pSD, TRUE, pDACL, FALSE)) { -// syslog(LOG_ERR, "SetSecurityDescriptorDacl() failed with error %d\n", -// GetLastError()); - goto end; +void D3D10Grabber::grab() { + DEBUG_HIGH_LEVEL << Q_FUNC_INFO << this->metaObject()->className(); + if (m_impl && m_impl->isStarted()) { + m_lastGrabResult = _grab(); + emit frameGrabAttempted(m_lastGrabResult); + } else { + emit grabberStateChangeRequested(true); } +} - bResult = TRUE; - -end: - if (pAuthenticatedUsersSID) FreeSid(pAuthenticatedUsersSID); - - if (bResult == FALSE) { - if (pDACL) HeapFree(GetProcessHeap(), 0, pDACL); - pDACL = NULL; +GrabResult D3D10Grabber::_grab() { + DEBUG_HIGH_LEVEL << Q_FUNC_INFO << this->metaObject()->className(); + if (!m_impl) { + return GrabResultFrameNotReady; } - return (PVOID) pDACL; + return m_impl->grab(m_grabResult, m_grabWidgets); } -VOID FreeRestrictedSD(PVOID ptr) { +D3D10Grabber::~D3D10Grabber() { +} - if (ptr) HeapFree(GetProcessHeap(), 0, ptr); +void D3D10Grabber::updateGrabMonitor(QWidget *widget) { + DEBUG_LOW_LEVEL << Q_FUNC_INFO << this->metaObject()->className(); + m_impl->updateGrabMonitor(widget); +} - return; +bool D3D10Grabber::isGrabbingStarted() const { + return m_impl->isStarted(); } +//void D3D10Grabber::setFallbackGrabber(GrabberBase *grabber) { +// m_fallbackGrabber = grabber; +//} + #endif diff --git a/Software/grab/D3D9Grabber.cpp b/Software/grab/D3D9Grabber.cpp index 8cce0d51..cfcf155f 100644 --- a/Software/grab/D3D9Grabber.cpp +++ b/Software/grab/D3D9Grabber.cpp @@ -1,284 +1,282 @@ -/* - * D3D9Grabber.cpp - * - * Created on: 19.09.2011 - * Project: Lightpack - * - * Copyright (c) 2011 Timur Sattarov - * - * Lightpack is a USB content-driving ambient lighting system - * - * Lightpack is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Lightpack is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -#include "D3D9Grabber.hpp" - -#ifdef D3D9_GRAB_SUPPORT - -#include -#include -#include "../src/debug.h" -#include "cmath" -#define BYTES_PER_PIXEL 4 - -D3D9Grabber::D3D9Grabber(QObject * parent, QList *grabResult, QList *grabAreasGeometry) - : TimeredGrabber(parent, grabResult, grabAreasGeometry), m_d3D(NULL), m_d3Device(NULL), m_surface(NULL) -{ - DEBUG_LOW_LEVEL << Q_FUNC_INFO; - - if ((m_d3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL) - { - DEBUG_LOW_LEVEL << "Cannot create Direct3D9 interface (Direct3DCreate9)"; - return; - } - - if (FAILED(m_d3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &m_displayMode))) - { - DEBUG_LOW_LEVEL << "Cannot get display mode for Direct3D9 (GetAdapterDisplayMode)"; - return; - } - - HWND hWnd = GetDesktopWindow(); // todo - - m_bufLength = 0; - - ZeroMemory(&m_presentParams, sizeof(D3DPRESENT_PARAMETERS)); - m_presentParams.Windowed = true; - m_presentParams.hDeviceWindow = hWnd; - m_presentParams.BackBufferFormat = m_displayMode.Format; - m_presentParams.BackBufferHeight = m_displayMode.Height; - m_presentParams.BackBufferWidth = m_displayMode.Width; - m_presentParams.MultiSampleType = D3DMULTISAMPLE_NONE; - m_presentParams.SwapEffect = D3DSWAPEFFECT_DISCARD; - //m_presentParams.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; todo - //m_presentParams.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; - - if (FAILED(m_d3D->CreateDevice( - D3DADAPTER_DEFAULT, - D3DDEVTYPE_HAL, - hWnd, - D3DCREATE_SOFTWARE_VERTEXPROCESSING, - &m_presentParams, - &m_d3Device))) - { - DEBUG_LOW_LEVEL << "Cannot create device for Direct3D9 (CreateDevice)"; - return; - } - - if (FAILED(m_d3Device->CreateOffscreenPlainSurface( - m_displayMode.Width, - m_displayMode.Height, - D3DFMT_A8R8G8B8, - D3DPOOL_SYSTEMMEM, - &m_surface, - NULL))) - { - DEBUG_LOW_LEVEL << "Cannot create offscreen surface for Direct3D9 (CreateOffscreenPlainSurface)"; - return; - } -} - -// todo move body to clear method -D3D9Grabber::~D3D9Grabber() -{ - DEBUG_LOW_LEVEL << Q_FUNC_INFO; - if (m_surface != NULL) - { - m_surface->Release(); - m_surface = NULL; - } - - if (m_d3Device != NULL) - { - m_d3Device->Release(); - m_d3Device = NULL; - } - - if (m_d3D != NULL) - { - m_d3D->Release(); - m_d3D = NULL; - } - - if (m_buf != NULL) - { - free(m_buf); - } -} - -const char * D3D9Grabber::getName() -{ - return "D3D9Grabber"; -} - -int D3D9Grabber::getBufLength(const RECT &rect) -{ - return (rect.right - rect.left) * (rect.bottom - rect.top) * BYTES_PER_PIXEL; -} - -GrabResult D3D9Grabber::_grab() -{ - D3DSURFACE_DESC surfaceDesc; - m_rect = getEffectiveRect(*m_grabWidgets); - m_surface->GetDesc(&surfaceDesc); - clipRect(&m_rect, &surfaceDesc); - int bufLengthNeeded = getBufLength(m_rect); - if (bufLengthNeeded > m_bufLength) - { - if(m_buf != NULL) - free(m_buf); - m_buf = (BYTE *)malloc(bufLengthNeeded); - m_bufLength = bufLengthNeeded; - } - getImageData(m_buf, m_rect); - m_grabResult->clear(); - foreach(GrabWidget * widget, *m_grabWidgets) { - m_grabResult->append( widget->isAreaEnabled() ? - getColor(widget->x(), widget->y(), widget->width(), widget->height()) : - qRgb(0,0,0) ); - } - return GrabResultOk; -} - -void D3D9Grabber::clipRect(RECT *rect, D3DSURFACE_DESC *surfaceDesc) { - if (rect->left < 0) { - rect->left = 0; - } - if (rect->right > surfaceDesc->Width) { - rect->right = surfaceDesc->Width; - } - if (rect->top < 0) { - rect->top = 0; - } - - if (rect->bottom > surfaceDesc->Height) { - rect->bottom = surfaceDesc->Height; - } -} - -RECT D3D9Grabber::getEffectiveRect(QList &widgets) -{ - RECT result = {0,0,0,0}; - if (widgets.size() > 0) - { - GrabWidget * widget = widgets[0]; - result.left = widget->x(); - result.right = widget->x() + widget->width(); - result.top = widget->y(); - result.bottom = widget->y() + widget->height(); - for(int i = 1; i < widgets.size(); i++) { - widget = widgets[i]; - if (result.left > widget->x()) - result.left = widget->x(); - if (result.right < widget->x() + widget->width()) - result.right = widget->x() + widget->width(); - if (result.top > widget->y()) - result.top = widget->y(); - if (result.bottom < widget->y() + widget->height()) - result.bottom = widget->y() + widget->height(); - } - } - return result; -} - -BYTE * D3D9Grabber::getImageData(BYTE * buf, RECT &rect) -{ - D3DLOCKED_RECT blockedRect; - D3DSURFACE_DESC surfaceDesc; - HRESULT result; - - m_d3Device->GetFrontBufferData(0, m_surface); - result = m_surface->LockRect(&blockedRect, &rect, D3DLOCK_READONLY); - if (result != D3D_OK) { - DEBUG_LOW_LEVEL << "Result not OK"; - } - m_surface->GetDesc(&surfaceDesc); -// kopiowanie UpdateSurface - CopyMemory(buf, blockedRect.pBits, getBufLength(rect)); - - m_surface->UnlockRect(); - return buf; -} - -QRgb D3D9Grabber::getColor(int x, int y, int width, int height) -{ - DEBUG_HIGH_LEVEL << Q_FUNC_INFO - << "x y w h:" << x << y << width << height; - - if (m_buf == NULL) - { - qCritical() << Q_FUNC_INFO << "m_buf == NULL"; - return 0; - } - - // Convert coordinates from "Main" desktop coord-system to capture-monitor coord-system - x -= m_rect.left; - y -= m_rect.top; - - // Ignore part of LED widget which out of screen - if( x < 0 ) { - width += x; /* reduce width */ - x = 0; - } - if( y < 0 ) { - height += y; /* reduce height */ - y = 0; - } - int screenWidth = m_rect.right - m_rect.left; - int screenHeight = m_rect.bottom - m_rect.top; - if( x + width > screenWidth ) width -= (x + width ) - screenWidth; - if( y + height > screenHeight ) height -= (y + height) - screenHeight; - - //calculate aligned width (align by 4 pixels) - width = width - (width % 4); - - if(width < 0 || height < 0){ - qWarning() << Q_FUNC_INFO << "width < 0 || height < 0:" << width << height; - - // width and height can't be negative - return 0x000000; - } - - unsigned count = 0; // count the amount of pixels taken into account - unsigned endIndex = (screenWidth * (y + height) + x + width) * BYTES_PER_PIXEL; - register unsigned index = (screenWidth * y + x) * BYTES_PER_PIXEL; // index of the selected pixel in pbPixelsBuff - register unsigned r = 0, g = 0, b = 0; - while (index < endIndex - width * BYTES_PER_PIXEL) { - for(int i = 0; i < width; i += 4) { - b += m_buf[index] + m_buf[index + 4] + m_buf[index + 8 ] + m_buf[index + 12]; - g += m_buf[index + 1] + m_buf[index + 5] + m_buf[index + 9 ] + m_buf[index + 13]; - r += m_buf[index + 2] + m_buf[index + 6] + m_buf[index + 10] + m_buf[index + 14]; - - count+=4; - index += BYTES_PER_PIXEL * 4; - } - - index += (screenWidth - width) * BYTES_PER_PIXEL; - } - - if( count != 0 ){ - r = (unsigned)round((double) r / count) & 0xff; - g = (unsigned)round((double) g / count) & 0xff; - b = (unsigned)round((double) b / count) & 0xff; - } - - QRgb result = qRgb(r, g, b); - - DEBUG_HIGH_LEVEL << Q_FUNC_INFO << "QRgb result =" << hex << result; - - return result; -} - -#endif // D3D9_GRAB_SUPPORT +/* + * D3D9Grabber.cpp + * + * Created on: 19.09.2011 + * Project: Lightpack + * + * Copyright (c) 2011 Timur Sattarov + * + * Lightpack is a USB content-driving ambient lighting system + * + * Lightpack is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Lightpack is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "D3D9Grabber.hpp" + +#ifdef D3D9_GRAB_SUPPORT + +#include +#include +#include "../src/debug.h" +#include "cmath" +#define BYTES_PER_PIXEL 4 + +#if defined _MSC_VER +#include "PrismatikMath.hpp" + +using PrismatikMath::round; +#endif // _MSC_VER + +D3D9Grabber::D3D9Grabber(QObject * parent, QList *grabResult, QList *grabAreasGeometry) + : TimeredGrabber(parent, grabResult, grabAreasGeometry), + m_d3D(NULL), m_d3Device(NULL), m_surface(NULL) +{ + DEBUG_LOW_LEVEL << Q_FUNC_INFO; + + if ((m_d3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL) + { + DEBUG_LOW_LEVEL << "Cannot create Direct3D9 interface (Direct3DCreate9)"; + return; + } + + if (FAILED(m_d3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &m_displayMode))) + { + DEBUG_LOW_LEVEL << "Cannot get display mode for Direct3D9 (GetAdapterDisplayMode)"; + return; + } + + HWND hWnd = GetDesktopWindow(); // todo + ZeroMemory(&m_presentParams, sizeof(D3DPRESENT_PARAMETERS)); + m_presentParams.Windowed = true; + m_presentParams.hDeviceWindow = hWnd; + m_presentParams.BackBufferFormat = m_displayMode.Format; + m_presentParams.BackBufferHeight = m_displayMode.Height; + m_presentParams.BackBufferWidth = m_displayMode.Width; + m_presentParams.MultiSampleType = D3DMULTISAMPLE_NONE; + m_presentParams.SwapEffect = D3DSWAPEFFECT_DISCARD; + //m_presentParams.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; todo + //m_presentParams.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + + if (FAILED(m_d3D->CreateDevice( + D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + hWnd, + D3DCREATE_SOFTWARE_VERTEXPROCESSING, + &m_presentParams, + &m_d3Device))) + { + DEBUG_LOW_LEVEL << "Cannot create device for Direct3D9 (CreateDevice)"; + return; + } + + if (FAILED(m_d3Device->CreateOffscreenPlainSurface( + m_displayMode.Width, + m_displayMode.Height, + D3DFMT_A8R8G8B8, + D3DPOOL_SYSTEMMEM, + &m_surface, + NULL))) + { + DEBUG_LOW_LEVEL << "Cannot create offscreen surface for Direct3D9 (CreateOffscreenPlainSurface)"; + return; + } +} + +// todo move body to clear method +D3D9Grabber::~D3D9Grabber() +{ + DEBUG_LOW_LEVEL << Q_FUNC_INFO; + if (m_surface != NULL) + { + m_surface->Release(); + m_surface = NULL; + } + + if (m_d3Device != NULL) + { + m_d3Device->Release(); + m_d3Device = NULL; + } + + if (m_d3D != NULL) + { + m_d3D->Release(); + m_d3D = NULL; + } +} + +const char * D3D9Grabber::getName() +{ + return "D3D9Grabber"; +} + +int D3D9Grabber::getBufLength(const RECT &rect) +{ + return (rect.right - rect.left) * (rect.bottom - rect.top) * BYTES_PER_PIXEL; +} + +GrabResult D3D9Grabber::_grab() +{ + D3DSURFACE_DESC surfaceDesc; + m_rect = getEffectiveRect(*m_grabWidgets); + m_surface->GetDesc(&surfaceDesc); + clipRect(&m_rect, &surfaceDesc); + int bufLengthNeeded = getBufLength(m_rect); + m_buf.resize(bufLengthNeeded); + getImageData(m_buf, m_rect); + m_grabResult->clear(); + foreach(GrabWidget * widget, *m_grabWidgets) { + m_grabResult->append( widget->isAreaEnabled() ? + getColor(widget->x(), widget->y(), widget->width(), widget->height()) : + qRgb(0,0,0) ); + } + return GrabResultOk; +} + +void D3D9Grabber::clipRect(RECT *rect, D3DSURFACE_DESC *surfaceDesc) { + if (rect->left < 0) { + rect->left = 0; + } + if (static_cast(rect->right) > surfaceDesc->Width) { + rect->right = surfaceDesc->Width; + } + if (rect->top < 0) { + rect->top = 0; + } + + if (static_cast(rect->bottom) > surfaceDesc->Height) { + rect->bottom = surfaceDesc->Height; + } +} + +RECT D3D9Grabber::getEffectiveRect(QList &widgets) +{ + RECT result = {0,0,0,0}; + if (widgets.size() > 0) + { + GrabWidget * widget = widgets[0]; + result.left = widget->x(); + result.right = widget->x() + widget->width(); + result.top = widget->y(); + result.bottom = widget->y() + widget->height(); + for(int i = 1; i < widgets.size(); i++) { + widget = widgets[i]; + if (result.left > widget->x()) + result.left = widget->x(); + if (result.right < widget->x() + widget->width()) + result.right = widget->x() + widget->width(); + if (result.top > widget->y()) + result.top = widget->y(); + if (result.bottom < widget->y() + widget->height()) + result.bottom = widget->y() + widget->height(); + } + } + return result; +} + +BYTE * D3D9Grabber::getImageData(QVector &buf, RECT &rect) +{ + D3DLOCKED_RECT blockedRect; + D3DSURFACE_DESC surfaceDesc; + HRESULT result; + + m_d3Device->GetFrontBufferData(0, m_surface); + result = m_surface->LockRect(&blockedRect, &rect, D3DLOCK_READONLY); + if (result != D3D_OK) { + DEBUG_LOW_LEVEL << "Result not OK"; + } + m_surface->GetDesc(&surfaceDesc); +// kopiowanie UpdateSurface + const int dataLength = getBufLength(rect); + if (dataLength > buf.size()) { + DEBUG_LOW_LEVEL << "Insufficient buffer length!"; + } + + CopyMemory(buf.data(), blockedRect.pBits, std::min(dataLength, buf.size())); + + m_surface->UnlockRect(); + return buf.data(); +} + +QRgb D3D9Grabber::getColor(int x, int y, int width, int height) +{ + DEBUG_HIGH_LEVEL << Q_FUNC_INFO + << "x y w h:" << x << y << width << height; + + if (m_buf.empty()) + { + qCritical() << Q_FUNC_INFO << "m_buf is empty!"; + return 0; + } + + // Convert coordinates from "Main" desktop coord-system to capture-monitor coord-system + x -= m_rect.left; + y -= m_rect.top; + + // Ignore part of LED widget which out of screen + if( x < 0 ) { + width += x; /* reduce width */ + x = 0; + } + if( y < 0 ) { + height += y; /* reduce height */ + y = 0; + } + int screenWidth = m_rect.right - m_rect.left; + int screenHeight = m_rect.bottom - m_rect.top; + if( x + width > screenWidth ) width -= (x + width ) - screenWidth; + if( y + height > screenHeight ) height -= (y + height) - screenHeight; + + //calculate aligned width (align by 4 pixels) + width = width - (width % 4); + + if(width < 0 || height < 0){ + qWarning() << Q_FUNC_INFO << "width < 0 || height < 0:" << width << height; + + // width and height can't be negative + return 0x000000; + } + + unsigned count = 0; // count the amount of pixels taken into account + unsigned endIndex = (screenWidth * (y + height) + x + width) * BYTES_PER_PIXEL; + register unsigned index = (screenWidth * y + x) * BYTES_PER_PIXEL; // index of the selected pixel in pbPixelsBuff + register unsigned r = 0, g = 0, b = 0; + while (index < endIndex - width * BYTES_PER_PIXEL) { + for(int i = 0; i < width; i += 4) { + b += m_buf[index] + m_buf[index + 4] + m_buf[index + 8 ] + m_buf[index + 12]; + g += m_buf[index + 1] + m_buf[index + 5] + m_buf[index + 9 ] + m_buf[index + 13]; + r += m_buf[index + 2] + m_buf[index + 6] + m_buf[index + 10] + m_buf[index + 14]; + + count+=4; + index += BYTES_PER_PIXEL * 4; + } + + index += (screenWidth - width) * BYTES_PER_PIXEL; + } + + if( count != 0 ){ + r = (unsigned)round((double) r / count) & 0xff; + g = (unsigned)round((double) g / count) & 0xff; + b = (unsigned)round((double) b / count) & 0xff; + } + + QRgb result = qRgb(r, g, b); + + DEBUG_HIGH_LEVEL << Q_FUNC_INFO << "QRgb result =" << hex << result; + + return result; +} + +#endif // D3D9_GRAB_SUPPORT diff --git a/Software/grab/TimeredGrabber.cpp b/Software/grab/TimeredGrabber.cpp index 48679467..376defa0 100644 --- a/Software/grab/TimeredGrabber.cpp +++ b/Software/grab/TimeredGrabber.cpp @@ -1,63 +1,66 @@ -/* - * TimeredGrabber.cpp - * - * Created on: 27.08.2012 - * Project: Lightpack - * - * Copyright (c) 2012 Timur Sattarov - * - * Lightpack a USB content-driving ambient lighting system - * - * Lightpack is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Lightpack is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - - -#include "TimeredGrabber.hpp" -#include "../src/debug.h" - -TimeredGrabber::TimeredGrabber(QObject * parent, QList *grabResult, QList *grabAreasGeometry) : GrabberBase(parent, grabResult, grabAreasGeometry) { -} - -TimeredGrabber::~TimeredGrabber() { - if (m_timer) - delete m_timer; -} - -void TimeredGrabber::init() { - DEBUG_LOW_LEVEL << Q_FUNC_INFO << this->metaObject()->className(); - m_timer = new QTimer(this); - connect(m_timer, SIGNAL(timeout()), this, SLOT(grab())); - m_timer->setSingleShot(false); -} - -void TimeredGrabber::setGrabInterval(int msec) { - DEBUG_LOW_LEVEL << Q_FUNC_INFO << this->metaObject()->className(); - m_timer->setInterval(msec); -} - -void TimeredGrabber::startGrabbing() { - DEBUG_LOW_LEVEL << Q_FUNC_INFO << this->metaObject()->className(); - m_timer->start(); -} - -void TimeredGrabber::stopGrabbing() { - DEBUG_LOW_LEVEL << Q_FUNC_INFO << this->metaObject()->className(); - m_timer->stop(); -} - -bool TimeredGrabber::isGrabbingStarted() const { - DEBUG_LOW_LEVEL << Q_FUNC_INFO << this->metaObject()->className(); - return m_timer->isActive(); -} +/* + * TimeredGrabber.cpp + * + * Created on: 27.08.2012 + * Project: Lightpack + * + * Copyright (c) 2012 Timur Sattarov + * + * Lightpack a USB content-driving ambient lighting system + * + * Lightpack is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Lightpack is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + + +#include "TimeredGrabber.hpp" + +#include +#include "../src/debug.h" + +TimeredGrabber::TimeredGrabber(QObject * parent, QList *grabResult, QList *grabAreasGeometry) + : GrabberBase(parent, grabResult, grabAreasGeometry) { +} + +TimeredGrabber::~TimeredGrabber() { + if (m_timer && m_timer->isActive()) + m_timer->stop(); +} + +void TimeredGrabber::init() { + DEBUG_LOW_LEVEL << Q_FUNC_INFO << this->metaObject()->className(); + m_timer.reset(new QTimer(this)); + connect(m_timer.data(), SIGNAL(timeout()), this, SLOT(grab())); + m_timer->setSingleShot(false); +} + +void TimeredGrabber::setGrabInterval(int msec) { + DEBUG_LOW_LEVEL << Q_FUNC_INFO << this->metaObject()->className(); + m_timer->setInterval(msec); +} + +void TimeredGrabber::startGrabbing() { + DEBUG_LOW_LEVEL << Q_FUNC_INFO << this->metaObject()->className(); + m_timer->start(); +} + +void TimeredGrabber::stopGrabbing() { + DEBUG_LOW_LEVEL << Q_FUNC_INFO << this->metaObject()->className(); + m_timer->stop(); +} + +bool TimeredGrabber::isGrabbingStarted() const { + DEBUG_LOW_LEVEL << Q_FUNC_INFO << this->metaObject()->className(); + return m_timer->isActive(); +} diff --git a/Software/grab/WinAPIGrabber.cpp b/Software/grab/WinAPIGrabber.cpp index d3bd3068..6cd852fb 100644 --- a/Software/grab/WinAPIGrabber.cpp +++ b/Software/grab/WinAPIGrabber.cpp @@ -1,219 +1,218 @@ -/* - * WinAPIGrabber.cpp - * - * Created on: 25.07.11 - * Project: Lightpack - * - * Copyright (c) 2011 Timur Sattarov, Mike Shatohin - * - * Lightpack a USB content-driving ambient lighting system - * - * Lightpack is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Lightpack is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -#include "WinAPIGrabber.hpp" -#ifdef WINAPI_GRAB_SUPPORT -#include "../src/debug.h" -#include -#include "calculations.hpp" -#include "../src/enums.hpp" - -WinAPIGrabber::WinAPIGrabber(QObject * parent, QList *grabResult, QList *grabAreasGeometry) - : TimeredGrabber(parent, grabResult, grabAreasGeometry) -{ - pbPixelsBuff = NULL; -} - -WinAPIGrabber::~WinAPIGrabber() -{ - freeDCs(); - delete[] pbPixelsBuff; -} - -void WinAPIGrabber::freeDCs() -{ - if (hScreenDC) - DeleteObject(hScreenDC); - - if (hBitmap) - DeleteObject(hBitmap); - - if (hMemDC) - DeleteObject(hMemDC); -} - -void WinAPIGrabber::updateGrabMonitor(QWidget *widget) -{ - HMONITOR hMonitorNew = MonitorFromWindow(reinterpret_cast(widget->winId()), MONITOR_DEFAULTTONEAREST); - if (hMonitor != hMonitorNew) { - hMonitor = hMonitorNew; - - ZeroMemory( &monitorInfo, sizeof(MONITORINFO) ); - monitorInfo.cbSize = sizeof(MONITORINFO); - - // Get position and resolution of the monitor - GetMonitorInfo( hMonitor, &monitorInfo ); - - screenWidth = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left; - screenHeight = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top; - - DEBUG_LOW_LEVEL << Q_FUNC_INFO << "screenWidth x screenHeight" << screenWidth << "x" << screenHeight; - - - freeDCs(); - - // CreateDC for multiple monitors - hScreenDC = CreateDC( TEXT("DISPLAY"), NULL, NULL, NULL ); - - // Create a bitmap compatible with the screen DC - hBitmap = CreateCompatibleBitmap( hScreenDC, screenWidth, screenHeight ); - - // Create a memory DC compatible to screen DC - hMemDC = CreateCompatibleDC( hScreenDC ); - - // Select new bitmap into memory DC - SelectObject( hMemDC, hBitmap ); - - DEBUG_LOW_LEVEL << Q_FUNC_INFO << "Allocate memory for pbPixelsBuff and update pixelsBuffSize, bytesPerPixel"; - - BITMAP * bmp = new BITMAP; - - // Now get the actual Bitmap - GetObject( hBitmap, sizeof(BITMAP), bmp ); - - // Calculate the size the buffer needs to be - unsigned pixelsBuffSizeNew = bmp->bmWidthBytes * bmp->bmHeight; - - DEBUG_LOW_LEVEL << Q_FUNC_INFO << "pixelsBuffSize =" << pixelsBuffSizeNew; - - if(pixelsBuffSize != pixelsBuffSizeNew){ - pixelsBuffSize = pixelsBuffSizeNew; - - // ReAllocate memory for new buffer size - if( pbPixelsBuff ) delete[] pbPixelsBuff; - - // Allocate - pbPixelsBuff = new BYTE[ pixelsBuffSize ]; - } - - // The amount of bytes per pixel is the amount of bits divided by 8 - bytesPerPixel = bmp->bmBitsPixel / 8; - - if( bytesPerPixel != 4 ){ - qDebug() << "Not 32-bit mode is not supported!" << bytesPerPixel; - } - - DeleteObject( bmp ); - } - -} - -GrabResult WinAPIGrabber::_grab() -{ - captureScreen(); - m_grabResult->clear(); - foreach(GrabWidget * widget, *m_grabWidgets) { - m_grabResult->append( widget->isAreaEnabled() ? getColor(widget) : qRgb(0,0,0) ); - } - return GrabResultOk; -} - -void WinAPIGrabber::captureScreen() -{ - DEBUG_HIGH_LEVEL << Q_FUNC_INFO; - - // Copy screen - BitBlt( hMemDC, 0, 0, screenWidth, screenHeight, hScreenDC, - monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.top, SRCCOPY ); - - // Get the actual RGB data and put it into pbPixelsBuff - GetBitmapBits( hBitmap, pixelsBuffSize, pbPixelsBuff ); -} - -QRgb WinAPIGrabber::getColor(const QWidget * grabme) -{ - DEBUG_HIGH_LEVEL << Q_FUNC_INFO; - - QRect widgetRect = grabme->frameGeometry(); - return getColor(widgetRect); -} - -QRgb WinAPIGrabber::getColor(const QRect &widgetRect) -{ - DEBUG_HIGH_LEVEL << Q_FUNC_INFO << Debug::toString(widgetRect); - - if (pbPixelsBuff == NULL) - { - qCritical() << Q_FUNC_INFO << "pbPixelsBuff == NULL"; - return 0; - } - - RECT rcMonitor = monitorInfo.rcMonitor; - QRect monitorRect = QRect( QPoint(rcMonitor.left, rcMonitor.top), QPoint(rcMonitor.right-1, rcMonitor.bottom-1)); - - QRect clippedRect = monitorRect.intersected(widgetRect); - - // Checking for the 'grabme' widget position inside the monitor that is used to capture color - if( !clippedRect.isValid() ){ - - DEBUG_MID_LEVEL << "Widget 'grabme' is out of screen:" << Debug::toString(clippedRect); - - // Widget 'grabme' is out of screen - return 0x000000; - } - - // Convert coordinates from "Main" desktop coord-system to capture-monitor coord-system - QRect preparedRect = clippedRect.translated(-monitorRect.x(), -monitorRect.y()); - - // Align width by 4 for accelerated calculations - preparedRect.setWidth(preparedRect.width() - (preparedRect.width() % 4)); - - if( !preparedRect.isValid() ){ - qWarning() << Q_FUNC_INFO << " preparedRect is not valid:" << Debug::toString(preparedRect); - - // width and height can't be negative - return 0x000000; - } - - using namespace Grab; - QRgb avgColor; - if (Calculations::calculateAvgColor(&avgColor, pbPixelsBuff, BufferFormatArgb, screenWidth * bytesPerPixel, preparedRect ) == 0) { - return avgColor; - } else { - return qRgb(0,0,0); - } - -#if 0 - if (screenWidth < 1920 && (r > 120 || g > 120 || b > 120)) { - int monitorWidth = screenWidth; - int monitorHeight = screenHeight; - const int BytesPerPixel = 4; - // Save image of screen: - QImage * im = new QImage( monitorWidth, monitorHeight, QImage::Format_RGB32 ); - for(int i=0; isetPixel(i, j, rgb); - } - } - im->save("screen.jpg"); - delete im; - } -#endif - -} - -#endif // WINAPI_GRAB_SUPPORT +/* + * WinAPIGrabber.cpp + * + * Created on: 25.07.11 + * Project: Lightpack + * + * Copyright (c) 2011 Timur Sattarov, Mike Shatohin + * + * Lightpack a USB content-driving ambient lighting system + * + * Lightpack is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Lightpack is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "WinAPIGrabber.hpp" +#ifdef WINAPI_GRAB_SUPPORT +#include "../src/debug.h" +#include +#include "calculations.hpp" +#include "../src/enums.hpp" + +WinAPIGrabber::WinAPIGrabber(QObject * parent, QList *grabResult, QList *grabAreasGeometry) + : TimeredGrabber(parent, grabResult, grabAreasGeometry), + hScreenDC(NULL), + hMemDC(NULL), + hBitmap(NULL) +{ +} + +WinAPIGrabber::~WinAPIGrabber() +{ + freeDCs(); +} + +void WinAPIGrabber::freeDCs() +{ + if (hScreenDC) + DeleteObject(hScreenDC); + + if (hBitmap) + DeleteObject(hBitmap); + + if (hMemDC) + DeleteObject(hMemDC); +} + +void WinAPIGrabber::updateMonitorInfo() +{ + ZeroMemory( &monitorInfo, sizeof(MONITORINFO) ); + monitorInfo.cbSize = sizeof(MONITORINFO); + + // Get position and resolution of the monitor + GetMonitorInfo( hMonitor, &monitorInfo ); + + screenWidth = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left; + screenHeight = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top; + + DEBUG_LOW_LEVEL << Q_FUNC_INFO << "screenWidth x screenHeight" << screenWidth << "x" << screenHeight; + + freeDCs(); + + // CreateDC for multiple monitors + hScreenDC = CreateDC( TEXT("DISPLAY"), NULL, NULL, NULL ); + + // Create a bitmap compatible with the screen DC + hBitmap = CreateCompatibleBitmap( hScreenDC, screenWidth, screenHeight ); + + // Create a memory DC compatible to screen DC + hMemDC = CreateCompatibleDC( hScreenDC ); + + // Select new bitmap into memory DC + SelectObject( hMemDC, hBitmap ); +} + +void WinAPIGrabber::resizePixelsBuffer() +{ + DEBUG_LOW_LEVEL << Q_FUNC_INFO << "Allocate memory for pbPixelsBuff and update pixelsBuffSize, bytesPerPixel"; + BITMAP bmp; + memset(&bmp, 0, sizeof(BITMAP)); + + // Now get the actual Bitmap + GetObject( hBitmap, sizeof(BITMAP), &bmp ); + + // Calculate the size the buffer needs to be + unsigned pixelsBuffSizeNew = bmp.bmWidthBytes * bmp.bmHeight; + + DEBUG_LOW_LEVEL << Q_FUNC_INFO << "pixelsBuffSize =" << pixelsBuffSizeNew; + + // ReAllocate memory for new buffer size + pbPixelsBuff.resize(pixelsBuffSizeNew); + + // The amount of bytes per pixel is the amount of bits divided by 8 + bytesPerPixel = bmp.bmBitsPixel / 8; + + if( bytesPerPixel != 4 ){ + qDebug() << "Not 32-bit mode is not supported!" << bytesPerPixel; + } +} + +void WinAPIGrabber::updateGrabMonitor(QWidget *widget) +{ + HMONITOR hMonitorNew = MonitorFromWindow(reinterpret_cast(widget->winId()), MONITOR_DEFAULTTONEAREST); + if (hMonitor != hMonitorNew) { + hMonitor = hMonitorNew; + + updateMonitorInfo(); + resizePixelsBuffer(); + } +} + +GrabResult WinAPIGrabber::_grab() +{ + captureScreen(); + m_grabResult->clear(); + foreach(GrabWidget * widget, *m_grabWidgets) { + m_grabResult->append( widget->isAreaEnabled() ? getColor(widget) : qRgb(0,0,0) ); + } + return GrabResultOk; +} + +void WinAPIGrabber::captureScreen() +{ + DEBUG_HIGH_LEVEL << Q_FUNC_INFO; + + // Copy screen + BitBlt( hMemDC, 0, 0, screenWidth, screenHeight, hScreenDC, + monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.top, SRCCOPY ); + + // Get the actual RGB data and put it into pbPixelsBuff + GetBitmapBits( hBitmap, pbPixelsBuff.size(), &pbPixelsBuff[0] ); +} + +QRgb WinAPIGrabber::getColor(const QWidget * grabme) +{ + DEBUG_HIGH_LEVEL << Q_FUNC_INFO; + + QRect widgetRect = grabme->frameGeometry(); + return getColor(widgetRect); +} + +QRgb WinAPIGrabber::getColor(const QRect &widgetRect) +{ + DEBUG_HIGH_LEVEL << Q_FUNC_INFO << Debug::toString(widgetRect); + + if (pbPixelsBuff.empty()) + { + qCritical() << Q_FUNC_INFO << "pbPixelsBuff is empty!"; + return 0; + } + + RECT rcMonitor = monitorInfo.rcMonitor; + QRect monitorRect = QRect( QPoint(rcMonitor.left, rcMonitor.top), QPoint(rcMonitor.right-1, rcMonitor.bottom-1)); + + QRect clippedRect = monitorRect.intersected(widgetRect); + + // Checking for the 'grabme' widget position inside the monitor that is used to capture color + if( !clippedRect.isValid() ){ + + DEBUG_MID_LEVEL << "Widget 'grabme' is out of screen:" << Debug::toString(clippedRect); + + // Widget 'grabme' is out of screen + return 0x000000; + } + + // Convert coordinates from "Main" desktop coord-system to capture-monitor coord-system + QRect preparedRect = clippedRect.translated(-monitorRect.x(), -monitorRect.y()); + + // Align width by 4 for accelerated calculations + preparedRect.setWidth(preparedRect.width() - (preparedRect.width() % 4)); + + if( !preparedRect.isValid() ){ + qWarning() << Q_FUNC_INFO << " preparedRect is not valid:" << Debug::toString(preparedRect); + + // width and height can't be negative + return 0x000000; + } + + using namespace Grab; + QRgb avgColor; + if (Calculations::calculateAvgColor(&avgColor, &pbPixelsBuff[0], BufferFormatArgb, screenWidth * bytesPerPixel, preparedRect ) == 0) { + return avgColor; + } else { + return qRgb(0,0,0); + } + +#if 0 + if (screenWidth < 1920 && (r > 120 || g > 120 || b > 120)) { + int monitorWidth = screenWidth; + int monitorHeight = screenHeight; + const int BytesPerPixel = 4; + // Save image of screen: + QImage * im = new QImage( monitorWidth, monitorHeight, QImage::Format_RGB32 ); + for(int i=0; isetPixel(i, j, rgb); + } + } + im->save("screen.jpg"); + delete im; + } +#endif + +} + +#endif // WINAPI_GRAB_SUPPORT diff --git a/Software/grab/WinAPIGrabberEachWidget.cpp b/Software/grab/WinAPIGrabberEachWidget.cpp index fa66eb64..07dffb6d 100644 --- a/Software/grab/WinAPIGrabberEachWidget.cpp +++ b/Software/grab/WinAPIGrabberEachWidget.cpp @@ -29,16 +29,20 @@ #include "../src/debug.h" #include +#if defined _MSC_VER +#include "PrismatikMath.hpp" + +using PrismatikMath::round; +#endif // _MSC_VER + WinAPIGrabberEachWidget::WinAPIGrabberEachWidget(QObject * parent, QList *grabResult, QList *grabAreasGeometry) - : TimeredGrabber(parent, grabResult, grabAreasGeometry) + : WinAPIGrabber(parent, grabResult, grabAreasGeometry), + isBufferNeedsResize(true) { - pbPixelsBuff = NULL; - isBufferNeedsResize = true; } WinAPIGrabberEachWidget::~WinAPIGrabberEachWidget() { - delete[] pbPixelsBuff; } const char * WinAPIGrabberEachWidget::getName() @@ -66,30 +70,7 @@ void WinAPIGrabberEachWidget::captureWidget(const QWidget * w) DEBUG_HIGH_LEVEL << Q_FUNC_INFO; if( isBufferNeedsResize ){ - - ZeroMemory( &monitorInfo, sizeof(MONITORINFO) ); - monitorInfo.cbSize = sizeof(MONITORINFO); - - // Get position and resolution of the monitor - GetMonitorInfo( hMonitor, &monitorInfo ); - - screenWidth = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left; - screenHeight = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top; - - DEBUG_LOW_LEVEL << Q_FUNC_INFO << "screenWidth x screenHeight" << screenWidth << "x" << screenHeight; - - - // CreateDC for multiple monitors - hScreenDC = CreateDC( TEXT("DISPLAY"), NULL, NULL, NULL ); - - // Create a bitmap compatible with the screen DC - hBitmap = CreateCompatibleBitmap( hScreenDC, screenWidth, screenHeight ); - - // Create a memory DC compatible to screen DC - hMemDC = CreateCompatibleDC( hScreenDC ); - - // Select new bitmap into memory DC - SelectObject( hMemDC, hBitmap ); + updateMonitorInfo(); } // Copy screen @@ -97,43 +78,13 @@ void WinAPIGrabberEachWidget::captureWidget(const QWidget * w) w->x(), w->y(), SRCCOPY ); if( isBufferNeedsResize ){ - - DEBUG_LOW_LEVEL << Q_FUNC_INFO << "Allocate memory for pbPixelsBuff and update pixelsBuffSize, bytesPerPixel"; - - BITMAP * bmp = new BITMAP; - - // Now get the actual Bitmap - GetObject( hBitmap, sizeof(BITMAP), bmp ); - - // Calculate the size the buffer needs to be - unsigned pixelsBuffSizeNew = bmp->bmWidthBytes * bmp->bmHeight; - - DEBUG_LOW_LEVEL << Q_FUNC_INFO << "pixelsBuffSize =" << pixelsBuffSizeNew; - - if(pixelsBuffSize != pixelsBuffSizeNew){ - pixelsBuffSize = pixelsBuffSizeNew; - - // ReAllocate memory for new buffer size - if( pbPixelsBuff ) delete[] pbPixelsBuff; - - // Allocate - pbPixelsBuff = new BYTE[ pixelsBuffSize ]; - } - - // The amount of bytes per pixel is the amount of bits divided by 8 - bytesPerPixel = bmp->bmBitsPixel / 8; - - if( bytesPerPixel != 4 ){ - qDebug() << "Not 32-bit mode is not supported!" << bytesPerPixel; - } - - DeleteObject( bmp ); + resizePixelsBuffer(); isBufferNeedsResize = false; } // Get the actual RGB data and put it into pbPixelsBuff - GetBitmapBits( hBitmap, pixelsBuffSize, pbPixelsBuff ); + GetBitmapBits( hBitmap, pbPixelsBuff.size(), &pbPixelsBuff[0] ); } QRgb WinAPIGrabberEachWidget::getColor(const QWidget * grabme) @@ -153,9 +104,9 @@ QRgb WinAPIGrabberEachWidget::getColor(int x, int y, int width, int height) DEBUG_HIGH_LEVEL << Q_FUNC_INFO << "x y w h:" << x << y << width << height; - if (pbPixelsBuff == NULL) + if (pbPixelsBuff.empty()) { - qCritical() << Q_FUNC_INFO << "pbPixelsBuff == NULL"; + qCritical() << Q_FUNC_INFO << "pbPixelsBuff is empty!"; return 0; } diff --git a/Software/grab/WinDXUtils.cpp b/Software/grab/WinDXUtils.cpp new file mode 100644 index 00000000..c5c80cf0 --- /dev/null +++ b/Software/grab/WinDXUtils.cpp @@ -0,0 +1,251 @@ +/* + * WinDXUtils.cpp + * + * Created on: 25.07.11 + * Project: Lightpack + * + * Copyright (c) 2011 Timur Sattarov, Mike Shatohin + * + * Lightpack a USB content-driving ambient lighting system + * + * Lightpack is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Lightpack is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "WinDXUtils.hpp" + +#include +#include +#include "../src/debug.h" + +#include "../../common/msvcstub.h" +#include +#include +#include +#include + +#define DXGI_PRESENT_FUNC_ORD 8 +#define D3D9_SCPRESENT_FUNC_ORD 3 +#define D3D9_PRESENT_FUNC_ORD 17 + +namespace WinUtils +{ + +UINT GetDxgiPresentOffset(HWND hwnd) { + Q_ASSERT(hwnd != NULL); + IDXGIFactory1 * factory = NULL; + IDXGIAdapter * adapter; + HRESULT hresult = CreateDXGIFactory(IID_IDXGIFactory, reinterpret_cast(&factory)); + if (hresult != S_OK) { + qCritical() << "Can't create DXGIFactory. " << hresult; + return 0; + } + hresult = factory->EnumAdapters(0, &adapter); + if (hresult != S_OK) { + qCritical() << "Can't enumerate adapters. " << hresult; + return 0; + } + + DXGI_MODE_DESC dxgiModeDesc; + dxgiModeDesc.Width = 1; + dxgiModeDesc.Height = 1; + dxgiModeDesc.RefreshRate.Numerator = 1; + dxgiModeDesc.RefreshRate.Denominator = 1; + dxgiModeDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + dxgiModeDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE; + dxgiModeDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + + DXGI_SAMPLE_DESC dxgiSampleDesc = {1, 0}; + + DXGI_SWAP_CHAIN_DESC dxgiSwapChainDesc; + memset(&dxgiSwapChainDesc, 0, sizeof(DXGI_SWAP_CHAIN_DESC)); + dxgiSwapChainDesc.BufferDesc = dxgiModeDesc; + dxgiSwapChainDesc.SampleDesc = dxgiSampleDesc; + dxgiSwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + dxgiSwapChainDesc.BufferCount = 2; + dxgiSwapChainDesc.OutputWindow = hwnd; + dxgiSwapChainDesc.Windowed = true; + dxgiSwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + dxgiSwapChainDesc.Flags = 0; + + IDXGISwapChain * pSc; + ID3D10Device * pDev; + hresult = D3D10CreateDeviceAndSwapChain(adapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, 0, D3D10_SDK_VERSION, &dxgiSwapChainDesc, &pSc, &pDev); + if (S_OK != hresult) { + qCritical() << Q_FUNC_INFO << QString("Can't create D3D10Device and SwapChain. hresult = 0x%1").arg(QString::number(hresult, 16)); + return 0; + } + + + uintptr_t * pvtbl = reinterpret_cast(pSc); + uintptr_t presentFuncPtr = *pvtbl + sizeof(void *)*DXGI_PRESENT_FUNC_ORD; + + char buf[100]; + sprintf(buf, "presentFuncPtr=%x", presentFuncPtr); + DEBUG_LOW_LEVEL << Q_FUNC_INFO << buf; + + intptr_t hDxgi = reinterpret_cast(GetModuleHandle(L"dxgi.dll")); + int presentFuncOffset = static_cast(presentFuncPtr - hDxgi); + + sprintf(buf, "presentFuncOffset=%x", presentFuncOffset); + DEBUG_LOW_LEVEL << Q_FUNC_INFO << buf; + + + pSc->Release(); + pDev->Release(); + adapter->Release(); + factory->Release(); + + return presentFuncOffset; +} + +typedef IDirect3D9 * (WINAPI *Direct3DCreate9Func)(UINT SDKVersion); +UINT GetD3D9PresentOffset(HWND hWnd){ + IDirect3D9 *pD3D = NULL; + HINSTANCE hD3d9 = LoadLibrary(L"d3d9.dll"); + Direct3DCreate9Func createDev = reinterpret_cast(GetProcAddress(hD3d9, "Direct3DCreate9")); + pD3D = createDev(D3D_SDK_VERSION); + if ( !pD3D) + { + qCritical() << "Test_DirectX9 Direct3DCreate9(%d) call FAILED" << D3D_SDK_VERSION ; + return 0; + } + + // step 3: Get IDirect3DDevice9 + D3DDISPLAYMODE d3ddm; + HRESULT hRes = pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm ); + if (FAILED(hRes)) + { + qCritical() << QString("Test_DirectX9 GetAdapterDisplayMode failed. 0x%x").arg( hRes); + return 0; + } + + D3DPRESENT_PARAMETERS d3dpp; + ZeroMemory( &d3dpp, sizeof(d3dpp)); + d3dpp.Windowed = true; + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + d3dpp.BackBufferFormat = d3ddm.Format; + + IDirect3DDevice9 *pD3DDevice; + hRes = pD3D->CreateDevice( + D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, // the device we suppose any app would be using. + hWnd, + D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_DISABLE_DRIVER_MANAGEMENT, + &d3dpp, &pD3DDevice); + if (FAILED(hRes)) + { + qCritical() << QString("Test_DirectX9 CreateDevice failed. 0x%x").arg(hRes); + return 0; + } + + IDirect3DSwapChain9 *pD3DSwapChain; + hRes = pD3DDevice->GetSwapChain( 0, &pD3DSwapChain); + if (FAILED(hRes)) + { + qCritical() << QString("Test_DirectX9 GetSwapChain failed. 0x%x").arg(hRes); + return 0; + } + else + { + uintptr_t * pvtbl = *((uintptr_t**)(pD3DDevice)); + uintptr_t presentFuncPtr = pvtbl[D3D9_PRESENT_FUNC_ORD]; + char buf[100]; + sprintf(buf, "presentFuncPtr=%x", presentFuncPtr); + DEBUG_LOW_LEVEL << Q_FUNC_INFO << buf; + + UINT presentFuncOffset = (presentFuncPtr - reinterpret_cast(hD3d9)); + + sprintf(buf, "presentFuncOffset=%x", presentFuncOffset); + DEBUG_LOW_LEVEL << Q_FUNC_INFO << buf; + + + pD3DSwapChain->Release(); + pD3DDevice->Release(); + pD3D->Release(); + + return presentFuncOffset; + } +} + +UINT GetD3D9SCPresentOffset(HWND hWnd){ + IDirect3D9 *pD3D = NULL; + HINSTANCE hD3d9 = LoadLibrary(L"d3d9.dll"); + Direct3DCreate9Func createDev = reinterpret_cast(GetProcAddress(hD3d9, "Direct3DCreate9")); + pD3D = createDev(D3D_SDK_VERSION); + if ( !pD3D) + { + qCritical() << "Test_DirectX9 Direct3DCreate9(%d) call FAILED" << D3D_SDK_VERSION ; + return 0; + } + + // step 3: Get IDirect3DDevice9 + D3DDISPLAYMODE d3ddm; + HRESULT hRes = pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm ); + if (FAILED(hRes)) + { + qCritical() << QString("Test_DirectX9 GetAdapterDisplayMode failed. 0x%x").arg( hRes); + return 0; + } + + D3DPRESENT_PARAMETERS d3dpp; + ZeroMemory( &d3dpp, sizeof(d3dpp)); + d3dpp.Windowed = true; + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + d3dpp.BackBufferFormat = d3ddm.Format; + + IDirect3DDevice9 *pD3DDevice; + hRes = pD3D->CreateDevice( + D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, // the device we suppose any app would be using. + hWnd, + D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_DISABLE_DRIVER_MANAGEMENT, + &d3dpp, &pD3DDevice); + if (FAILED(hRes)) + { + qCritical() << QString("Test_DirectX9 CreateDevice failed. 0x%x").arg(hRes); + return 0; + } + + IDirect3DSwapChain9 *pD3DSwapChain; + hRes = pD3DDevice->GetSwapChain( 0, &pD3DSwapChain); + if (FAILED(hRes)) + { + qCritical() << QString("Test_DirectX9 GetSwapChain failed. 0x%x").arg(hRes); + return 0; + } + else + { + uintptr_t * pvtbl = *((uintptr_t**)(pD3DSwapChain)); + uintptr_t presentFuncPtr = pvtbl[D3D9_SCPRESENT_FUNC_ORD]; + char buf[100]; + sprintf(buf, "presentFuncPtr=%x", presentFuncPtr); + DEBUG_LOW_LEVEL << Q_FUNC_INFO << buf; + + void *pD3d9 = reinterpret_cast(hD3d9); + UINT presentFuncOffset = (presentFuncPtr - reinterpret_cast(pD3d9)); + + sprintf(buf, "presentFuncOffset=%x", presentFuncOffset); + DEBUG_LOW_LEVEL << Q_FUNC_INFO << buf; + + + pD3DSwapChain->Release(); + pD3DDevice->Release(); + pD3D->Release(); + + return presentFuncOffset; + } +} + +} // namespace WinUtils diff --git a/Software/grab/WinUtils.cpp b/Software/grab/WinUtils.cpp new file mode 100644 index 00000000..a2e837d6 --- /dev/null +++ b/Software/grab/WinUtils.cpp @@ -0,0 +1,251 @@ +/* + * WinUtils.cpp + * + * Created on: 25.07.11 + * Project: Lightpack + * + * Copyright (c) 2011 Timur Sattarov, Mike Shatohin + * + * Lightpack a USB content-driving ambient lighting system + * + * Lightpack is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Lightpack is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "WinUtils.hpp" + +#include +#include +#include + +#include "../src/debug.h" + +#define SIZEOF_ARRAY(a) (sizeof(a)/sizeof(a[0])) + +namespace WinUtils +{ + +const WCHAR lightpackHooksDllName[] = L"prismatik-hooks.dll"; +static LPCWSTR pwstrExcludeProcesses[]={L"skype.exe", L"chrome.exe", L"firefox.exe"}; + +BOOL SetPrivilege(HANDLE hToken, LPCTSTR szPrivName, BOOL fEnable) { + + TOKEN_PRIVILEGES tp; + tp.PrivilegeCount = 1; + LookupPrivilegeValue(NULL, szPrivName, &tp.Privileges[0].Luid); + tp.Privileges[0].Attributes = fEnable ? SE_PRIVILEGE_ENABLED : 0; + AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof (tp), NULL, NULL); + return ((GetLastError() == ERROR_SUCCESS)); + +} + +BOOL AcquirePrivileges() { + + HANDLE hCurrentProc = GetCurrentProcess(); + HANDLE hCurrentProcToken; + + if (!OpenProcessToken(hCurrentProc, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hCurrentProcToken)) { +// syslog(LOG_ERR, "OpenProcessToken Error %u", GetLastError()); + } else { + if (!SetPrivilege(hCurrentProcToken, SE_DEBUG_NAME, TRUE)) { +// syslog(LOG_ERR, "SetPrivleges SE_DEBUG_NAME Error %u", GetLastError()); + } else { + return TRUE; + } + } + return FALSE; +} + +QList * getDxProcessesIDs(QList * processes, LPCWSTR wstrSystemRootPath) { + + DWORD aProcesses[1024]; + HMODULE hMods[1024]; + DWORD cbNeeded; + DWORD cProcesses; + char debug_buf[255]; + WCHAR executableName[MAX_PATH]; + unsigned int i; + + // Get the list of process identifiers. + processes->clear(); + + if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) ) + return NULL; + + // Calculate how many process identifiers were returned. + + cProcesses = cbNeeded / sizeof(DWORD); + + // Print the names of the modules for each process. + + for ( i = 0; i < cProcesses; i++ ) + { + if (aProcesses[i] != GetCurrentProcessId()) { + HANDLE hProcess; + hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | + PROCESS_VM_READ, + FALSE, aProcesses[i] ); + if (NULL == hProcess) + goto nextProcess; + + GetModuleFileNameExW(hProcess, 0, executableName, sizeof (executableName)); + + if (wcsstr(executableName, wstrSystemRootPath) != NULL) { + goto nextProcess; + } + + PathStripPathW(executableName); + + ::WideCharToMultiByte(CP_ACP, 0, executableName, -1, debug_buf, 255, NULL, NULL); + DEBUG_MID_LEVEL << Q_FUNC_INFO << debug_buf; + + for (unsigned k=0; k < SIZEOF_ARRAY(pwstrExcludeProcesses); k++) { + if (wcsicmp(executableName, pwstrExcludeProcesses[k])== 0) { + DEBUG_MID_LEVEL << Q_FUNC_INFO << "skipping " << pwstrExcludeProcesses; + goto nextProcess; + } + } + + // Get a list of all the modules in this process. + + if( EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) + { + bool isDXPresent = false; + for ( DWORD j = 0; j < (cbNeeded / sizeof(HMODULE)); j++ ) + { + WCHAR szModName[MAX_PATH]; + + if ( GetModuleFileNameExW( hProcess, hMods[j], szModName, + sizeof(szModName) / sizeof(WCHAR))) + { + + PathStripPathW(szModName); + ::WideCharToMultiByte(CP_ACP, 0, szModName, -1, debug_buf, 255, NULL, NULL); + DEBUG_HIGH_LEVEL << Q_FUNC_INFO << debug_buf; + + if(wcsicmp(szModName, lightpackHooksDllName) == 0) { + goto nextProcess; + } else { + if (wcsicmp(szModName, L"d3d9.dll") == 0 || + wcsicmp(szModName, L"dxgi.dll") == 0 ) + isDXPresent = true; + } + } + } + if (isDXPresent) + processes->append(aProcesses[i]); + + } +nextProcess: + // Release the handle to the process. + CloseHandle( hProcess ); + } + } + + return processes; +} + + +PVOID BuildRestrictedSD(PSECURITY_DESCRIPTOR pSD) { + DWORD dwAclLength; + PSID pAuthenticatedUsersSID = NULL; + PACL pDACL = NULL; + BOOL bResult = FALSE; + SID_IDENTIFIER_AUTHORITY siaNT = SECURITY_NT_AUTHORITY; + + // initialize the security descriptor + if (!InitializeSecurityDescriptor(pSD, + SECURITY_DESCRIPTOR_REVISION)) { +// syslog(LOG_ERR, "InitializeSecurityDescriptor() failed with error %d\n", +// GetLastError()); + goto end; + } + + // obtain a sid for the Authenticated Users Group + if (!AllocateAndInitializeSid(&siaNT, 1, + SECURITY_AUTHENTICATED_USER_RID, 0, 0, 0, 0, 0, 0, 0, + &pAuthenticatedUsersSID)) { +// syslog(LOG_ERR, "AllocateAndInitializeSid() failed with error %d\n", +// GetLastError()); + goto end; + } + + // NOTE: + // + // The Authenticated Users group includes all user accounts that + // have been successfully authenticated by the system. If access + // must be restricted to a specific user or group other than + // Authenticated Users, the SID can be constructed using the + // LookupAccountSid() API based on a user or group name. + + // calculate the DACL length + dwAclLength = sizeof(ACL) + // add space for Authenticated Users group ACE + + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + + GetLengthSid(pAuthenticatedUsersSID); + + // allocate memory for the DACL + pDACL = (PACL) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + dwAclLength); + if (!pDACL) { +// syslog(LOG_ERR, "HeapAlloc() failed with error %d\n", GetLastError()); + goto end; + } + + // initialize the DACL + if (!InitializeAcl(pDACL, dwAclLength, ACL_REVISION)) { +// syslog(LOG_ERR, "InitializeAcl() failed with error %d\n", +// GetLastError()); + goto end; + } + + // add the Authenticated Users group ACE to the DACL with + // GENERIC_READ, GENERIC_WRITE, and GENERIC_EXECUTE access + + if (!AddAccessAllowedAce(pDACL, ACL_REVISION, + MAXIMUM_ALLOWED , + pAuthenticatedUsersSID)) { +// syslog(LOG_ERR, "AddAccessAllowedAce() failed with error %d\n", +// GetLastError()); + goto end; + } + + // set the DACL in the security descriptor + if (!SetSecurityDescriptorDacl(pSD, TRUE, pDACL, FALSE)) { +// syslog(LOG_ERR, "SetSecurityDescriptorDacl() failed with error %d\n", +// GetLastError()); + goto end; + } + + bResult = TRUE; + +end: + if (pAuthenticatedUsersSID) FreeSid(pAuthenticatedUsersSID); + + if (bResult == FALSE) { + if (pDACL) HeapFree(GetProcessHeap(), 0, pDACL); + pDACL = NULL; + } + + return (PVOID) pDACL; +} + +VOID FreeRestrictedSD(PVOID ptr) { + + if (ptr) HeapFree(GetProcessHeap(), 0, ptr); + + return; +} + +} // namespace WinUtils diff --git a/Software/grab/X11Grabber.cpp b/Software/grab/X11Grabber.cpp index d240dd7f..0dffbbe8 100644 --- a/Software/grab/X11Grabber.cpp +++ b/Software/grab/X11Grabber.cpp @@ -1,246 +1,250 @@ -/* - * X11Grabber.cpp - * - * Created on: 25.06.11 - * Project: Lightpack - * - * Copyright (c) 2011 Andrey Isupov, Timur Sattarov, Mike Shatohin - * - * Lightpack a USB content-driving ambient lighting system - * - * Lightpack is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Lightpack is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -#include "X11Grabber.hpp" - -#ifdef X11_GRAB_SUPPORT - -#include -// x shared-mem extension -#include -#include -#include -#include - -struct X11GrabberData -{ - Display *display; - Screen *Xscreen; - XImage *image; - XShmSegmentInfo shminfo; -}; - -X11Grabber::X11Grabber(QObject *parent, QList *grabResult, QList *grabAreasGeometry) - : TimeredGrabber(parent, grabResult, grabAreasGeometry) -{ - this->updateScreenAndAllocateMemory = true; - this->screen = 0; - d = new X11GrabberData(); - d->image = NULL; - d->display = XOpenDisplay(NULL); -} - -X11Grabber::~X11Grabber() -{ - XCloseDisplay(d->display); - delete d; -} - -const char * X11Grabber::getName() -{ - return "X11Grabber"; -} -void X11Grabber::updateGrabMonitor(QWidget *widget) -{ - DEBUG_HIGH_LEVEL << Q_FUNC_INFO; -// updateScreenAndAllocateMemory = true; -// screen = QApplication::desktop()->screenNumber( widget ); -} - -QList X11Grabber::grabWidgetsColors(QList &widgets) -{ - captureScreen(); - QList result; - for(int i = 0; i < widgets.size(); i++) { - result.append(getColor(widgets[i])); - } - return result; -} - -GrabResult X11Grabber::_grab() -{ - captureScreen(); - m_grabResult->clear(); - foreach(GrabWidget * widget, *m_grabWidgets) { - m_grabResult->append( widget->isAreaEnabled() ? getColor(widget) : qRgb(0,0,0) ); - } - return GrabResultOk; -} - -void X11Grabber::captureScreen() -{ - DEBUG_HIGH_LEVEL << Q_FUNC_INFO; - - if( updateScreenAndAllocateMemory ){ - //screenres = QApplication::desktop()->screenGeometry(screen); - updateScreenAndAllocateMemory = false; - - // todo test and fix dual monitor configuration - d->Xscreen = DefaultScreenOfDisplay(d->display); - - long width=DisplayWidth(d->display, screen); - long height=DisplayHeight(d->display, screen); - - DEBUG_HIGH_LEVEL << "dimensions " << width << "x" << height << screen; - screenres = QRect(0,0,width,height); - - if (d->image != NULL) { - XShmDetach(d->display, &d->shminfo); - XDestroyImage(d->image); - shmdt (d->shminfo.shmaddr); - shmctl(d->shminfo.shmid, IPC_RMID, 0); - } - d->image = XShmCreateImage(d->display, DefaultVisualOfScreen(d->Xscreen), - DefaultDepthOfScreen(d->Xscreen), - ZPixmap, NULL, &d->shminfo, - screenres.width(), screenres.height() ); - uint imagesize; - imagesize = d->image->bytes_per_line * d->image->height; - d->shminfo.shmid = shmget( IPC_PRIVATE, - imagesize, - IPC_CREAT|0777 - ); - - char* mem = (char*)shmat(d->shminfo.shmid, 0, 0); - d->shminfo.shmaddr = mem; - d->image->data = mem; - d->shminfo.readOnly = False; - - XShmAttach(d->display, &d->shminfo); - } - // DEBUG_LOW_LEVEL << "XShmGetImage"; - XShmGetImage(d->display, - RootWindow(d->display, screen), - d->image, - 0, - 0, - 0x00FFFFFF - ); -#if 0 - DEBUG_LOW_LEVEL << "QImage"; - QImage *pic = new QImage(1024,768,QImage::Format_RGB32); - DEBUG_LOW_LEVEL << "format"; - unsigned long pixel; - for (int y = 0; y < 768; y++) - { - for (int x = 0; x < 1024; x++) - { - pixel = XGetPixel(image, x, y); - int r = (pixel >> 16) & 0xff; - int g = (pixel >> 8) & 0xff; - int b = (pixel >> 0) & 0xff; - //QRgb rgb = QRgb() (r,g,b); - pic->setPixel(x,y,pixel); - } - } - DEBUG_LOW_LEVEL << "save"; - pic->save("/home/atarity/.Lightpack/test.bmp"); -#endif -} - -QRgb X11Grabber::getColor(const QWidget * grabme) -{ - DEBUG_HIGH_LEVEL << Q_FUNC_INFO; - - return getColor(grabme->x(), - grabme->y(), - grabme->width(), - grabme->height()); -} - -QRgb X11Grabber::getColor(int x, int y, int width, int height) -{ - DEBUG_HIGH_LEVEL << Q_FUNC_INFO - << "x y w h:" << x << y << width << height; - - // Checking for the 'grabme' widget position inside the monitor that is used to capture color - if( x + width < screenres.left() || - x > screenres.right() || - y + height < screenres.top() || - y > screenres.bottom() ){ - - DEBUG_MID_LEVEL << "Widget 'grabme' is out of screen, x y w h:" << x << y << width << height; - - // Widget 'grabme' is out of screen - return 0x000000; - } - - // Convert coordinates from "Main" desktop coord-system to capture-monitor coord-system - x -= screenres.left() ; - y -= screenres.top(); - - // Ignore part of LED widget which out of screen - if( x < 0 ) { - width += x; /* reduce width */ - x = 0; - } - if( y < 0 ) { - height += y; /* reduce height */ - y = 0; - } - if( x + width > (int)screenres.width() ) width -= (x + width ) - screenres.width(); - if( y + height > (int)screenres.height() ) height -= (y + height) - screenres.height(); - - //calculate aligned width (align by 4 pixels) - width = width - (width % 4); - - if(width < 0 || height < 0){ - qWarning() << Q_FUNC_INFO << "width < 0 || height < 0:" << width << height; - - // width and height can't be negative - return 0x000000; - } - - register unsigned r=0,g=0,b=0; - - unsigned char *pbPixelsBuff; - int bytesPerPixel = d->image->bits_per_pixel / 8; - pbPixelsBuff = (unsigned char *)d->image->data; - int count = 0; // count the amount of pixels taken into account - for(int j = 0; j < height; j++) { - int index = d->image->bytes_per_line * (y+j) + x * bytesPerPixel; - for(int i = 0; i < width; i+=4) { - b += pbPixelsBuff[index] + pbPixelsBuff[index + 4] + pbPixelsBuff[index + 8 ] + pbPixelsBuff[index + 12]; - g += pbPixelsBuff[index+1] + pbPixelsBuff[index + 5] + pbPixelsBuff[index + 9 ] + pbPixelsBuff[index + 13]; - r += pbPixelsBuff[index+2] + pbPixelsBuff[index + 6] + pbPixelsBuff[index + 10] + pbPixelsBuff[index + 14]; - count+=4; - index += bytesPerPixel * 4; - } - - } - - if( count != 0 ){ - r = (unsigned)round((double) r / count) & 0xff; - g = (unsigned)round((double) g / count) & 0xff; - b = (unsigned)round((double) b / count) & 0xff; - } - - QRgb result = qRgb(r,g,b);// im.pixel(0,0); - - DEBUG_HIGH_LEVEL << "QRgb result =" << hex << result; - - return result; -} -#endif // X11_GRAB_SUPPORT +/* + * X11Grabber.cpp + * + * Created on: 25.06.11 + * Project: Lightpack + * + * Copyright (c) 2011 Andrey Isupov, Timur Sattarov, Mike Shatohin + * + * Lightpack a USB content-driving ambient lighting system + * + * Lightpack is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Lightpack is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "X11Grabber.hpp" + +#ifdef X11_GRAB_SUPPORT + +#include +#include +#include +// x shared-mem extension +#include +#include +#include +#include + +struct X11GrabberData +{ + Display *display; + Screen *Xscreen; + XImage *image; + XShmSegmentInfo shminfo; +}; + +X11Grabber::X11Grabber(QObject *parent, QList *grabResult, QList *grabAreasGeometry) + : TimeredGrabber(parent, grabResult, grabAreasGeometry) +{ + this->updateScreenAndAllocateMemory = true; + this->screen = 0; + data = new X11GrabberData(); + data->image = NULL; + data->display = XOpenDisplay(NULL); +} + +X11Grabber::~X11Grabber() +{ + if (data->image) + XDestroyImage(data->image); + XCloseDisplay(data->display); +} + +const char * X11Grabber::getName() +{ + return "X11Grabber"; +} +void X11Grabber::updateGrabMonitor(QWidget *widget) +{ + DEBUG_HIGH_LEVEL << Q_FUNC_INFO; +// updateScreenAndAllocateMemory = true; +// screen = QApplication::desktop()->screenNumber( widget ); +} + +QList X11Grabber::grabWidgetsColors(QList &widgets) +{ + captureScreen(); + QList result; + for(int i = 0; i < widgets.size(); i++) { + result.append(getColor(widgets[i])); + } + return result; +} + +GrabResult X11Grabber::_grab() +{ + captureScreen(); + m_grabResult->clear(); + foreach(GrabWidget * widget, *m_grabWidgets) { + m_grabResult->append( widget->isAreaEnabled() ? getColor(widget) : qRgb(0,0,0) ); + } + return GrabResultOk; +} + +void X11Grabber::captureScreen() +{ + DEBUG_HIGH_LEVEL << Q_FUNC_INFO; + + if( updateScreenAndAllocateMemory ){ + //screenres = QApplication::desktop()->screenGeometry(screen); + updateScreenAndAllocateMemory = false; + + // todo test and fix dual monitor configuration + data->Xscreen = DefaultScreenOfDisplay(data->display); + + long width=DisplayWidth(data->display, screen); + long height=DisplayHeight(data->display, screen); + + DEBUG_HIGH_LEVEL << "dimensions " << width << "x" << height << screen; + screenres = QRect(0,0,width,height); + + if (data->image != NULL) { + XShmDetach(data->display, &data->shminfo); + XDestroyImage(data->image); + shmdt (data->shminfo.shmaddr); + shmctl(data->shminfo.shmid, IPC_RMID, 0); + } + data->image = XShmCreateImage( + data->display, + DefaultVisualOfScreen(data->Xscreen), + DefaultDepthOfScreen(data->Xscreen), + ZPixmap, NULL, &data->shminfo, + screenres.width(), screenres.height()); + + uint imagesize = data->image->bytes_per_line * data->image->height; + data->shminfo.shmid = shmget(IPC_PRIVATE, + imagesize, + IPC_CREAT | 0777); + + char* mem = (char*)shmat(data->shminfo.shmid, 0, 0); + data->shminfo.shmaddr = mem; + data->image->data = mem; + data->shminfo.readOnly = False; + + XShmAttach(data->display, &data->shminfo); + } + // DEBUG_LOW_LEVEL << "XShmGetImage"; + XShmGetImage(data->display, + RootWindow(data->display, screen), + data->image, + 0, + 0, + 0x00FFFFFF + ); +#if 0 + DEBUG_LOW_LEVEL << "QImage"; + QImage *pic = new QImage(1024,768,QImage::Format_RGB32); + DEBUG_LOW_LEVEL << "format"; + unsigned long pixel; + for (int y = 0; y < 768; y++) + { + for (int x = 0; x < 1024; x++) + { + pixel = XGetPixel(image, x, y); + int r = (pixel >> 16) & 0xff; + int g = (pixel >> 8) & 0xff; + int b = (pixel >> 0) & 0xff; + //QRgb rgb = QRgb() (r,g,b); + pic->setPixel(x,y,pixel); + } + } + DEBUG_LOW_LEVEL << "save"; + pic->save("/home/atarity/.Lightpack/test.bmp"); +#endif +} + +QRgb X11Grabber::getColor(const QWidget * grabme) +{ + DEBUG_HIGH_LEVEL << Q_FUNC_INFO; + + return getColor(grabme->x(), + grabme->y(), + grabme->width(), + grabme->height()); +} + +QRgb X11Grabber::getColor(int x, int y, int width, int height) +{ + DEBUG_HIGH_LEVEL << Q_FUNC_INFO + << "x y w h:" << x << y << width << height; + + // Checking for the 'grabme' widget position inside the monitor that is used to capture color + if( x + width < screenres.left() || + x > screenres.right() || + y + height < screenres.top() || + y > screenres.bottom() ){ + + DEBUG_MID_LEVEL << "Widget 'grabme' is out of screen, x y w h:" << x << y << width << height; + + // Widget 'grabme' is out of screen + return 0x000000; + } + + // Convert coordinates from "Main" desktop coord-system to capture-monitor coord-system + x -= screenres.left() ; + y -= screenres.top(); + + // Ignore part of LED widget which out of screen + if( x < 0 ) { + width += x; /* reduce width */ + x = 0; + } + if( y < 0 ) { + height += y; /* reduce height */ + y = 0; + } + if( x + width > (int)screenres.width() ) width -= (x + width ) - screenres.width(); + if( y + height > (int)screenres.height() ) height -= (y + height) - screenres.height(); + + //calculate aligned width (align by 4 pixels) + width = width - (width % 4); + + if(width < 0 || height < 0){ + qWarning() << Q_FUNC_INFO << "width < 0 || height < 0:" << width << height; + + // width and height can't be negative + return 0x000000; + } + + register unsigned r=0,g=0,b=0; + + unsigned char *pbPixelsBuff; + int bytesPerPixel = data->image->bits_per_pixel / 8; + pbPixelsBuff = (unsigned char *)data->image->data; + int count = 0; // count the amount of pixels taken into account + for(int j = 0; j < height; j++) { + int index = data->image->bytes_per_line * (y+j) + x * bytesPerPixel; + for(int i = 0; i < width; i+=4) { + b += pbPixelsBuff[index] + pbPixelsBuff[index + 4] + pbPixelsBuff[index + 8 ] + pbPixelsBuff[index + 12]; + g += pbPixelsBuff[index+1] + pbPixelsBuff[index + 5] + pbPixelsBuff[index + 9 ] + pbPixelsBuff[index + 13]; + r += pbPixelsBuff[index+2] + pbPixelsBuff[index + 6] + pbPixelsBuff[index + 10] + pbPixelsBuff[index + 14]; + count+=4; + index += bytesPerPixel * 4; + } + + } + + if( count != 0 ){ + r = (unsigned)round((double) r / count) & 0xff; + g = (unsigned)round((double) g / count) & 0xff; + b = (unsigned)round((double) b / count) & 0xff; + } + + QRgb result = qRgb(r,g,b);// im.pixel(0,0); + + DEBUG_HIGH_LEVEL << "QRgb result =" << hex << result; + + return result; +} +#endif // X11_GRAB_SUPPORT diff --git a/Software/grab/calculations.cpp b/Software/grab/calculations.cpp index b4f86627..07fac147 100644 --- a/Software/grab/calculations.cpp +++ b/Software/grab/calculations.cpp @@ -1,123 +1,187 @@ -/* - * calculations.cpp - * - * Created on: 23.07.2012 - * Project: Lightpack - * - * Copyright (c) 2012 Timur Sattarov - * - * Lightpack a USB content-driving ambient lighting system - * - * Lightpack is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Lightpack is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -#include "calculations.hpp" - -namespace Grab { - namespace Calculations { - - const char bytesPerPixel = 4; - - QRgb calculateAvgColor(QRgb *result, const unsigned char *buffer, BufferFormat bufferFormat, unsigned int pitch, const QRect &rect ) { - - Q_ASSERT_X(rect.width() % 4 == 0, "average color calculation", "rect width should be aligned by 4 bytes"); - - int count = 0; // count the amount of pixels taken into account - register unsigned int r=0, g=0, b=0; - - switch(bufferFormat) { - case BufferFormatArgb: - - for(int currentY = 0; currentY < rect.height(); currentY++) { - int index = pitch * (rect.y()+currentY) + rect.x()*bytesPerPixel; - for(int currentX = 0; currentX < rect.width(); currentX += 4) { - b += buffer[index] + buffer[index + 4] + buffer[index + 8 ] + buffer[index + 12]; - g += buffer[index+1] + buffer[index + 5] + buffer[index + 9 ] + buffer[index + 13]; - r += buffer[index+2] + buffer[index + 6] + buffer[index + 10] + buffer[index + 14]; - count += 4; - index += bytesPerPixel * 4; - } - - } - break; - - case BufferFormatAbgr: - for(int currentY = 0; currentY < rect.height(); currentY++) { - int index = pitch * (rect.y()+currentY) + rect.x()*bytesPerPixel; - for(int currentX = 0; currentX < rect.width(); currentX += 4) { - r += buffer[index] + buffer[index + 4] + buffer[index + 8 ] + buffer[index + 12]; - g += buffer[index+1] + buffer[index + 5] + buffer[index + 9 ] + buffer[index + 13]; - b += buffer[index+2] + buffer[index + 6] + buffer[index + 10] + buffer[index + 14]; - count += 4; - index += bytesPerPixel * 4; - } - } - break; - - case BufferFormatRgba: - for(int currentY = 0; currentY < rect.height(); currentY++) { - int index = pitch * (rect.y()+currentY) + rect.x()*bytesPerPixel; - for(int currentX = 0; currentX < rect.width(); currentX += 4) { - b += buffer[index+1] + buffer[index + 5] + buffer[index + 9 ] + buffer[index + 13]; - g += buffer[index+2] + buffer[index + 6] + buffer[index + 10] + buffer[index + 14]; - r += buffer[index+3] + buffer[index + 7] + buffer[index + 11] + buffer[index + 15]; - count += 4; - index += bytesPerPixel * 4; - } - - } - break; - case BufferFormatBgra: - for(int currentY = 0; currentY < rect.height(); currentY++) { - int index = pitch * (rect.y()+currentY) + rect.x()*bytesPerPixel; - for(int currentX = 0; currentX < rect.width(); currentX += 4) { - r += buffer[index+1] + buffer[index + 5] + buffer[index + 9 ] + buffer[index + 13]; - g += buffer[index+2] + buffer[index + 6] + buffer[index + 10] + buffer[index + 14]; - b += buffer[index+3] + buffer[index + 7] + buffer[index + 11] + buffer[index + 15]; - count += 4; - index += bytesPerPixel * 4; - } - - } - break; - default: - return -1; - break; - } - - if ( count > 1 ) { - r = ( r / count) & 0xff; - g = ( g / count) & 0xff; - b = ( b / count) & 0xff; - } - - *result = qRgb(r,g,b); - return 0; - } - - QRgb calculateAvgColor(QList *colors) { - int r=0, g=0, b=0; - for( int i=0; isize(); i++) { - r += qRed(colors->at(i)); - g += qGreen(colors->at(i)); - b += qBlue(colors->at(i)); - } - r = r / colors->size(); - g = g / colors->size(); - b = b / colors->size(); - return qRgb(r, g, b); - } - } -} +/* + * calculations.cpp + * + * Created on: 23.07.2012 + * Project: Lightpack + * + * Copyright (c) 2012 Timur Sattarov + * + * Lightpack a USB content-driving ambient lighting system + * + * Lightpack is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Lightpack is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "calculations.hpp" + +namespace { + const char bytesPerPixel = 4; + + struct ColorValue { + int r, g, b; + }; + + static int accumulateBufferFormatArgb( + const unsigned char *buffer, + unsigned int pitch, + const QRect &rect, + ColorValue *resultColor) { + register unsigned int r=0, g=0, b=0; + int count = 0; // count the amount of pixels taken into account + for(int currentY = 0; currentY < rect.height(); currentY++) { + int index = pitch * (rect.y()+currentY) + rect.x()*bytesPerPixel; + for(int currentX = 0; currentX < rect.width(); currentX += 4) { + b += buffer[index] + buffer[index + 4] + buffer[index + 8 ] + buffer[index + 12]; + g += buffer[index+1] + buffer[index + 5] + buffer[index + 9 ] + buffer[index + 13]; + r += buffer[index+2] + buffer[index + 6] + buffer[index + 10] + buffer[index + 14]; + count += 4; + index += bytesPerPixel * 4; + } + } + + resultColor->r = r; + resultColor->g = g; + resultColor->b = b; + return count; + } + + static int accumulateBufferFormatAbgr( + const unsigned char *buffer, + unsigned int pitch, + const QRect &rect, + ColorValue *resultColor) { + register unsigned int r=0, g=0, b=0; + int count = 0; // count the amount of pixels taken into account + for(int currentY = 0; currentY < rect.height(); currentY++) { + int index = pitch * (rect.y()+currentY) + rect.x()*bytesPerPixel; + for(int currentX = 0; currentX < rect.width(); currentX += 4) { + r += buffer[index] + buffer[index + 4] + buffer[index + 8 ] + buffer[index + 12]; + g += buffer[index+1] + buffer[index + 5] + buffer[index + 9 ] + buffer[index + 13]; + b += buffer[index+2] + buffer[index + 6] + buffer[index + 10] + buffer[index + 14]; + count += 4; + index += bytesPerPixel * 4; + } + } + + resultColor->r = r; + resultColor->g = g; + resultColor->b = b; + return count; + } + + static int accumulateBufferFormatRgba( + const unsigned char *buffer, + unsigned int pitch, + const QRect &rect, + ColorValue *resultColor) { + register unsigned int r=0, g=0, b=0; + int count = 0; // count the amount of pixels taken into account + for(int currentY = 0; currentY < rect.height(); currentY++) { + int index = pitch * (rect.y()+currentY) + rect.x()*bytesPerPixel; + for(int currentX = 0; currentX < rect.width(); currentX += 4) { + b += buffer[index+1] + buffer[index + 5] + buffer[index + 9 ] + buffer[index + 13]; + g += buffer[index+2] + buffer[index + 6] + buffer[index + 10] + buffer[index + 14]; + r += buffer[index+3] + buffer[index + 7] + buffer[index + 11] + buffer[index + 15]; + count += 4; + index += bytesPerPixel * 4; + } + } + + resultColor->r = r; + resultColor->g = g; + resultColor->b = b; + return count; + } + + static int accumulateBufferFormatBgra( + const unsigned char *buffer, + unsigned int pitch, + const QRect &rect, + ColorValue *resultColor) { + register unsigned int r=0, g=0, b=0; + int count = 0; // count the amount of pixels taken into account + for(int currentY = 0; currentY < rect.height(); currentY++) { + int index = pitch * (rect.y()+currentY) + rect.x()*bytesPerPixel; + for(int currentX = 0; currentX < rect.width(); currentX += 4) { + r += buffer[index+1] + buffer[index + 5] + buffer[index + 9 ] + buffer[index + 13]; + g += buffer[index+2] + buffer[index + 6] + buffer[index + 10] + buffer[index + 14]; + b += buffer[index+3] + buffer[index + 7] + buffer[index + 11] + buffer[index + 15]; + count += 4; + index += bytesPerPixel * 4; + } + } + + resultColor->r = r; + resultColor->g = g; + resultColor->b = b; + return count; + } +} // namespace + +namespace Grab { + namespace Calculations { + QRgb calculateAvgColor(QRgb *result, const unsigned char *buffer, BufferFormat bufferFormat, unsigned int pitch, const QRect &rect ) { + + Q_ASSERT_X(rect.width() % 4 == 0, "average color calculation", "rect width should be aligned by 4 bytes"); + + int count = 0; // count the amount of pixels taken into account + ColorValue color = {0, 0, 0}; + + switch(bufferFormat) { + case BufferFormatArgb: + count = accumulateBufferFormatArgb(buffer, pitch, rect, &color); + break; + + case BufferFormatAbgr: + count = accumulateBufferFormatAbgr(buffer, pitch, rect, &color); + break; + + case BufferFormatRgba: + count = accumulateBufferFormatRgba(buffer, pitch, rect, &color); + break; + + case BufferFormatBgra: + count = accumulateBufferFormatBgra(buffer, pitch, rect, &color); + break; + default: + return -1; + break; + } + + if ( count > 1 ) { + color.r = ( color.r / count) & 0xff; + color.g = ( color.g / count) & 0xff; + color.b = ( color.b / count) & 0xff; + } + + *result = qRgb(color.r, color.g, color.b); + return 0; + } + + QRgb calculateAvgColor(QList *colors) { + int r=0, g=0, b=0; + const int size = colors->size(); + for( int i=0; i < size; i++) { + const QRgb rgb = colors->at(i); + r += qRed(rgb); + g += qGreen(rgb); + b += qBlue(rgb); + } + r = r / size; + g = g / size; + b = b / size; + return qRgb(r, g, b); + } + } +} diff --git a/Software/grab/grab.pro b/Software/grab/grab.pro index d992783a..80f79ad3 100644 --- a/Software/grab/grab.pro +++ b/Software/grab/grab.pro @@ -13,7 +13,9 @@ CONFIG += staticlib include(../build-config.prf) -INCLUDEPATH += ./include ../src +LIBS += -lprismatik-math + +INCLUDEPATH += ./include ../src ../math/include HEADERS += \ include/calculations.hpp \ @@ -31,17 +33,33 @@ SOURCES += \ GrabberBase.cpp win32 { - INCLUDEPATH += "$${DIRECTX_SDK_DIR}/Include" + # This will suppress gcc warnings in DX headers. + CONFIG(gcc) { + QMAKE_CXXFLAGS += -isystem "$${DIRECTX_SDK_DIR}/Include" + } else { + INCLUDEPATH += "$${DIRECTX_SDK_DIR}/Include" + } + + # This will suppress many MSVC warnings about 'unsecure' CRT functions. + CONFIG(msvc) { + DEFINES += _CRT_SECURE_NO_WARNINGS _CRT_NONSTDC_NO_DEPRECATE + } + HEADERS += \ + ../common/msvcstub.h \ include/D3D9Grabber.hpp \ include/D3D10Grabber.hpp \ include/WinAPIGrabberEachWidget.hpp \ - include/WinAPIGrabber.hpp + include/WinAPIGrabber.hpp \ + include/WinUtils.hpp \ + include/WinDXUtils.hpp SOURCES += \ D3D9Grabber.cpp \ D3D10Grabber.cpp \ WinAPIGrabberEachWidget.cpp \ - WinAPIGrabber.cpp + WinAPIGrabber.cpp \ + WinUtils.cpp \ + WinDXUtils.cpp } macx { diff --git a/Software/grab/include/D3D10Grabber.hpp b/Software/grab/include/D3D10Grabber.hpp index c408ab68..abeeb4be 100644 --- a/Software/grab/include/D3D10Grabber.hpp +++ b/Software/grab/include/D3D10Grabber.hpp @@ -27,32 +27,18 @@ #include #ifdef D3D10_GRAB_SUPPORT -//#define WINVER 0x0500 -#include -#include"../../common/D3D10GrabberDefs.hpp" #include -#include<../libraryinjector/ILibraryInjector.h> +#include -typedef HWND (*GetHwndCallback_t)(); +typedef void* (*GetHwndCallback_t)(); -class D3D10GrabberWorker: public QObject { - Q_OBJECT - public: - D3D10GrabberWorker(QObject *parent, LPSECURITY_ATTRIBUTES lpsa); - ~D3D10GrabberWorker(); - private: - HANDLE m_frameGrabbedEvent; - signals: - void frameGrabbed(); - public slots: - void runLoop(); -}; +class D3D10GrabberImpl; class D3D10Grabber : public GrabberBase { - Q_OBJECT + public: D3D10Grabber(QObject * parent, QList *grabResult, QList *grabWidgets, GetHwndCallback_t getHwndCb); ~D3D10Grabber(); @@ -66,37 +52,12 @@ public slots: virtual void updateGrabMonitor(QWidget * firstWidget); virtual void startGrabbing(); virtual void stopGrabbing(); - virtual bool isGrabbingStarted() const { return m_isStarted; } + virtual bool isGrabbingStarted() const; virtual void setGrabInterval(int msec); virtual void grab(); -private slots: - void infectCleanDxProcesses(void); - void handleIfFrameGrabbed(); - private: - bool initIPC(LPSECURITY_ATTRIBUTES lpsa); - void freeIPC(); - QRgb getColor(QRect &widgetRect); - QTimer *m_checkIfFrameGrabbedTimer; - - static HANDLE m_sharedMem; - static HANDLE m_mutex; - static bool m_isStarted; - static PVOID m_memMap; - D3D10GrabberWorker *m_worker; - QThread * m_workerThread; -// GrabberBase * m_fallbackGrabber; - HOOKSGRABBER_SHARED_MEM_DESC m_memDesc; - static UINT m_lastFrameId; - static MONITORINFO m_monitorInfo; - static QTimer * m_processesScanAndInfectTimer; - static bool m_isInited; - static ILibraryInjector * m_libraryInjector; - static WCHAR m_hooksLibPath[300]; - static WCHAR m_systemrootPath[300]; - static bool m_isFrameGrabbedDuringLastSecond; - static GetHwndCallback_t m_getHwndCb; + QScopedPointer m_impl; }; #endif diff --git a/Software/grab/include/D3D9Grabber.hpp b/Software/grab/include/D3D9Grabber.hpp index 3f771689..6e3195d9 100644 --- a/Software/grab/include/D3D9Grabber.hpp +++ b/Software/grab/include/D3D9Grabber.hpp @@ -30,6 +30,14 @@ #ifdef D3D9_GRAB_SUPPORT +// includes +#if !defined NOMINMAX +#define NOMINMAX +#endif + +#if !defined WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif #include using namespace Grab; @@ -45,24 +53,22 @@ class D3D9Grabber : public TimeredGrabber protected: virtual GrabResult _grab(); -private: - LPDIRECT3D9 m_d3D; - LPDIRECT3DDEVICE9 m_d3Device; - LPDIRECT3DSURFACE9 m_surface; - D3DDISPLAYMODE m_displayMode; - D3DPRESENT_PARAMETERS m_presentParams; - int m_bufLength; - BYTE * m_buf; - RECT m_rect; private: BYTE * expandBuffer(BYTE * buf, int newLength); - BYTE * getImageData(BYTE *, RECT &); + BYTE * getImageData(QVector &, RECT &); RECT getEffectiveRect(QList &widgets); int getBufLength(const RECT &rect); QRgb getColor(int x, int y, int width, int height); void clipRect(RECT *rect, D3DSURFACE_DESC *surfaceDesc); - +private: + LPDIRECT3D9 m_d3D; + LPDIRECT3DDEVICE9 m_d3Device; + LPDIRECT3DSURFACE9 m_surface; + D3DDISPLAYMODE m_displayMode; + D3DPRESENT_PARAMETERS m_presentParams; + QVector m_buf; + RECT m_rect; }; #endif // D3D9_GRAB_SUPPORT diff --git a/Software/grab/include/TimeredGrabber.hpp b/Software/grab/include/TimeredGrabber.hpp index e110eb43..e9c35f90 100644 --- a/Software/grab/include/TimeredGrabber.hpp +++ b/Software/grab/include/TimeredGrabber.hpp @@ -1,51 +1,53 @@ -/* - * TimeredGrabber.hpp - * - * Created on: 27.08.2012 - * Project: Lightpack - * - * Copyright (c) 2012 Timur Sattarov - * - * Lightpack a USB content-driving ambient lighting system - * - * Lightpack is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Lightpack is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - - -#ifndef TIMEREDGRABBER_HPP -#define TIMEREDGRABBER_HPP - -#include -#include "GrabberBase.hpp" - -class TimeredGrabber : public GrabberBase -{ - Q_OBJECT -public: - TimeredGrabber(QObject * parent, QList *grabResult, QList *grabAreasGeometry); - ~TimeredGrabber(); -public slots: - virtual void init(); - virtual GrabResult _grab() = 0; - virtual void startGrabbing(); - virtual void stopGrabbing(); - virtual bool isGrabbingStarted() const; - virtual void setGrabInterval(int msec); - -protected: - QTimer *m_timer; -}; - -#endif // TIMEREDGRABBER_HPP +/* + * TimeredGrabber.hpp + * + * Created on: 27.08.2012 + * Project: Lightpack + * + * Copyright (c) 2012 Timur Sattarov + * + * Lightpack a USB content-driving ambient lighting system + * + * Lightpack is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Lightpack is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + + +#ifndef TIMEREDGRABBER_HPP +#define TIMEREDGRABBER_HPP + +#include +#include "GrabberBase.hpp" + +QT_FORWARD_DECLARE_CLASS(QTimer) + +class TimeredGrabber : public GrabberBase +{ + Q_OBJECT +public: + TimeredGrabber(QObject * parent, QList *grabResult, QList *grabAreasGeometry); + ~TimeredGrabber(); + +public slots: + virtual void init(); + virtual void startGrabbing(); + virtual void stopGrabbing(); + virtual bool isGrabbingStarted() const; + virtual void setGrabInterval(int msec); + +protected: + QScopedPointer m_timer; +}; + +#endif // TIMEREDGRABBER_HPP diff --git a/Software/grab/include/WinAPIGrabber.hpp b/Software/grab/include/WinAPIGrabber.hpp index 17bf21f6..f3abb69a 100644 --- a/Software/grab/include/WinAPIGrabber.hpp +++ b/Software/grab/include/WinAPIGrabber.hpp @@ -1,74 +1,87 @@ -/* - * WinAPIGrabber.hpp - * - * Created on: 25.07.11 - * Project: Lightpack - * - * Copyright (c) 2011 Timur Sattarov, Mike Shatohin - * - * Lightpack a USB content-driving ambient lighting system - * - * Lightpack is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Lightpack is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -#pragma once - -#include "TimeredGrabber.hpp" -#include "../src/enums.hpp" -#ifdef WINAPI_GRAB_SUPPORT - -#define WINVER 0x0500 /* Windows2000 for MonitorFromWindow(..) func */ - -#include - -using namespace Grab; - -class WinAPIGrabber : public TimeredGrabber -{ - Q_OBJECT -public: - WinAPIGrabber(QObject *parent, QList *grabResult, QList *grabAreasGeometry); - ~WinAPIGrabber(); - -protected: - virtual GrabResult _grab(); - -public slots: - virtual void updateGrabMonitor(QWidget *widget); -private: - void captureScreen(); - void freeDCs(); - QRgb getColor(const QWidget * grabme); - QRgb getColor(const QRect &widgetRect); - -private: - HMONITOR hMonitor; - MONITORINFO monitorInfo; - - // Size of screen in pixels, initialize in captureScreen() using in getColor() - unsigned screenWidth; - unsigned screenHeight; - - // Captured screen buffer, contains actual RGB data in reversed order - BYTE * pbPixelsBuff; - unsigned pixelsBuffSize; - unsigned bytesPerPixel; - - HDC hScreenDC; - HDC hMemDC; - HBITMAP hBitmap; - -}; -#endif // WINAPI_GRAB_SUPPORT +/* + * WinAPIGrabber.hpp + * + * Created on: 25.07.11 + * Project: Lightpack + * + * Copyright (c) 2011 Timur Sattarov, Mike Shatohin + * + * Lightpack a USB content-driving ambient lighting system + * + * Lightpack is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Lightpack is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#pragma once + +#include +#include "TimeredGrabber.hpp" +#include "../src/enums.hpp" + +#ifdef WINAPI_GRAB_SUPPORT + +#if defined WINVER && WINVER < 0x0500 +#undef WINVER +#endif + +#if !defined WINVER +#define WINVER 0x0500 /* Windows2000 for MonitorFromWindow(..) func */ +#endif +#if !defined NOMINMAX +#define NOMINMAX +#endif + +#if !defined WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#include + +class WinAPIGrabber : public TimeredGrabber +{ + Q_OBJECT +public: + WinAPIGrabber(QObject *parent, QList *grabResult, QList *grabAreasGeometry); + ~WinAPIGrabber(); + +public slots: + virtual void updateGrabMonitor(QWidget *widget); + +protected: + virtual GrabResult _grab(); + void freeDCs(); + void captureScreen(); + QRgb getColor(const QWidget * grabme); + QRgb getColor(const QRect &widgetRect); + void updateMonitorInfo(); + void resizePixelsBuffer(); + +protected: + HMONITOR hMonitor; + MONITORINFO monitorInfo; + + // Size of screen in pixels, initialize in captureScreen() using in getColor() + unsigned screenWidth; + unsigned screenHeight; + + // Captured screen buffer, contains actual RGB data in reversed order + QVector pbPixelsBuff; + unsigned bytesPerPixel; + + HDC hScreenDC; + HDC hMemDC; + HBITMAP hBitmap; +}; + +#endif // WINAPI_GRAB_SUPPORT diff --git a/Software/grab/include/WinAPIGrabberEachWidget.hpp b/Software/grab/include/WinAPIGrabberEachWidget.hpp index b1d26650..12c6a0bb 100644 --- a/Software/grab/include/WinAPIGrabberEachWidget.hpp +++ b/Software/grab/include/WinAPIGrabberEachWidget.hpp @@ -25,17 +25,12 @@ #pragma once -#include "TimeredGrabber.hpp" +#include "WinAPIGrabber.hpp" #include "../src/enums.hpp" #ifdef WINAPI_GRAB_SUPPORT -#define WINVER 0x0500 /* Windows2000 for MonitorFromWindow(..) func */ -#include - -using namespace Grab; - -class WinAPIGrabberEachWidget : public TimeredGrabber +class WinAPIGrabberEachWidget : public WinAPIGrabber { public: WinAPIGrabberEachWidget(QObject * parent, QList *grabResult, QList *grabAreasGeometry); @@ -52,22 +47,7 @@ class WinAPIGrabberEachWidget : public TimeredGrabber QRgb getColor(int x, int y, int width, int height); private: - HMONITOR hMonitor; bool isBufferNeedsResize; - MONITORINFO monitorInfo; - - // Size of screen in pixels, initialize in captureScreen() using in getColor() - unsigned screenWidth; - unsigned screenHeight; - - // Captured screen buffer, contains actual RGB data in reversed order - BYTE * pbPixelsBuff; - unsigned pixelsBuffSize; - unsigned bytesPerPixel; - - HDC hScreenDC; - HDC hMemDC; - HBITMAP hBitmap; - }; + #endif // WINAPI_GRAB_SUPPORT diff --git a/Software/grab/include/WinDXUtils.hpp b/Software/grab/include/WinDXUtils.hpp new file mode 100644 index 00000000..7a5dc6fe --- /dev/null +++ b/Software/grab/include/WinDXUtils.hpp @@ -0,0 +1,53 @@ +/* + * WinUtils.hpp + * + * Created on: 25.07.11 + * Project: Lightpack + * + * Copyright (c) 2011 Timur Sattarov, Mike Shatohin + * + * Lightpack a USB content-driving ambient lighting system + * + * Lightpack is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Lightpack is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#ifndef WINDXUTILS_HPP +#define WINDXUTILS_HPP + +#pragma once + +#if !defined NOMINMAX +#define NOMINMAX +#endif + +#if !defined WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include + +namespace WinUtils +{ +/*! + We are not allowed to create DXGIFactory inside of Dll, so determine SwapChain->Present vtbl location here. + To determine location we need to create SwapChain instance and dereference pointer. + \param hWnd window handle to bind SwapChain to + \return UINT +*/ +UINT GetDxgiPresentOffset(HWND hWnd); +UINT GetD3D9PresentOffset(HWND hWnd); +UINT GetD3D9SCPresentOffset(HWND hWnd); +} + +#endif // WINDXUTILS_HPP diff --git a/Software/grab/include/WinUtils.hpp b/Software/grab/include/WinUtils.hpp new file mode 100644 index 00000000..56529d3f --- /dev/null +++ b/Software/grab/include/WinUtils.hpp @@ -0,0 +1,58 @@ +/* + * WinUtils.hpp + * + * Created on: 25.07.11 + * Project: Lightpack + * + * Copyright (c) 2011 Timur Sattarov, Mike Shatohin + * + * Lightpack a USB content-driving ambient lighting system + * + * Lightpack is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Lightpack is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#ifndef WINUTILS_HPP +#define WINUTILS_HPP + +#pragma once + +#if !defined NOMINMAX +#define NOMINMAX +#endif + +#if !defined WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#include + +namespace WinUtils +{ +extern const WCHAR lightpackHooksDllName[]; + +BOOL SetPrivilege(HANDLE hToken, LPCTSTR szPrivName, BOOL fEnable); + +BOOL AcquirePrivileges(); + +QList * getDxProcessesIDs(QList * processes, LPCWSTR wstrSystemRootPath); + +PVOID BuildRestrictedSD(PSECURITY_DESCRIPTOR pSD); + +// The following function frees memory allocated in the +// BuildRestrictedSD() function +VOID FreeRestrictedSD(PVOID ptr); +} + +#endif // WINUTILS_HPP diff --git a/Software/grab/include/X11Grabber.hpp b/Software/grab/include/X11Grabber.hpp index add187bd..19901a94 100644 --- a/Software/grab/include/X11Grabber.hpp +++ b/Software/grab/include/X11Grabber.hpp @@ -1,71 +1,64 @@ -/* - * X11Grabber.hpp - * - * Created on: 25.06.11 - * Project: Lightpack - * - * Copyright (c) 2011 Andrey Isupov, Timur Sattarov, Mike Shatohin - * - * Lightpack a USB content-driving ambient lighting system - * - * Lightpack is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Lightpack is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -#pragma once - -#include "TimeredGrabber.hpp" -#include "../src/enums.hpp" - -#ifdef X11_GRAB_SUPPORT - - -//#include -//#include -#include -#include - -#include - -#include "../src/debug.h" - -struct X11GrabberData; - -using namespace Grab; - -class X11Grabber : public TimeredGrabber -{ -public: - X11Grabber(QObject *parent, QList *grabResult, QList *grabAreasGeometry); - ~X11Grabber(); - virtual const char * getName(); - virtual void updateGrabMonitor( QWidget * widget ); - virtual QList grabWidgetsColors(QList &widgets); - -protected: - virtual GrabResult _grab(); - -private: - void captureScreen(); - QRgb getColor(const QWidget * grabme); - QRgb getColor(int x, int y, int width, int height); - -private: - bool updateScreenAndAllocateMemory; - int screen; - QRect screenres; - - X11GrabberData *d; -}; -#endif // X11_GRAB_SUPPORT +/* + * X11Grabber.hpp + * + * Created on: 25.06.11 + * Project: Lightpack + * + * Copyright (c) 2011 Andrey Isupov, Timur Sattarov, Mike Shatohin + * + * Lightpack a USB content-driving ambient lighting system + * + * Lightpack is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Lightpack is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#pragma once + +#include "TimeredGrabber.hpp" +#include "../src/enums.hpp" + +#ifdef X11_GRAB_SUPPORT + +#include +#include "../src/debug.h" + +struct X11GrabberData; + +using namespace Grab; + +class X11Grabber : public TimeredGrabber +{ +public: + X11Grabber(QObject *parent, QList *grabResult, QList *grabAreasGeometry); + ~X11Grabber(); + virtual const char * getName(); + virtual void updateGrabMonitor( QWidget * widget ); + virtual QList grabWidgetsColors(QList &widgets); + +protected: + virtual GrabResult _grab(); + +private: + void captureScreen(); + QRgb getColor(const QWidget * grabme); + QRgb getColor(int x, int y, int width, int height); + +private: + bool updateScreenAndAllocateMemory; + int screen; + QRect screenres; + + QScopedPointer data; +}; +#endif // X11_GRAB_SUPPORT diff --git a/Software/grab/include/calculations.hpp b/Software/grab/include/calculations.hpp index ce85580a..9c2c8085 100644 --- a/Software/grab/include/calculations.hpp +++ b/Software/grab/include/calculations.hpp @@ -1,39 +1,39 @@ -/* - * calculations.hpp - * - * Created on: 16.07.2012 - * Project: Lightpack - * - * Copyright (c) 2012 Timur Sattarov - * - * Lightpack a USB content-driving ambient lighting system - * - * Lightpack is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Lightpack is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -#pragma once - -#include "QRect" -#include "QRgb" -#include "QList" -#include "../common/BufferFormat.h" - -namespace Grab { - namespace Calculations { - - QRgb calculateAvgColor(QRgb *result, const unsigned char *buffer, BufferFormat bufferFormat, unsigned int pitch, const QRect &rect ); - QRgb calculateAvgColor(QList *colors); - } -} +/* + * calculations.hpp + * + * Created on: 16.07.2012 + * Project: Lightpack + * + * Copyright (c) 2012 Timur Sattarov + * + * Lightpack a USB content-driving ambient lighting system + * + * Lightpack is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Lightpack is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#pragma once + +#include +#include +#include +#include "../common/BufferFormat.h" + +namespace Grab { + namespace Calculations { + + QRgb calculateAvgColor(QRgb *result, const unsigned char *buffer, BufferFormat bufferFormat, unsigned int pitch, const QRect &rect ); + QRgb calculateAvgColor(QList *colors); + } +}