From c4490946b964c4ec46340fc10581563d7a9e0c37 Mon Sep 17 00:00:00 2001 From: Corey C Date: Wed, 17 Oct 2012 00:43:59 -0400 Subject: [PATCH 01/20] wfreerdp-server: small cleanup of rdpsnd; added debug code for creating d3d11 device --- server/Windows/wf_dxgi.c | 21 +++++++++++++- server/Windows/wf_rdpsnd.c | 58 ++++++++++++++++++++++---------------- 2 files changed, 54 insertions(+), 25 deletions(-) diff --git a/server/Windows/wf_dxgi.c b/server/Windows/wf_dxgi.c index 4a22a546f..6cfb8d90b 100644 --- a/server/Windows/wf_dxgi.c +++ b/server/Windows/wf_dxgi.c @@ -85,12 +85,31 @@ int wf_dxgi_init(wfInfo* context) D3D11_SDK_VERSION, &gDevice, &FeatureLevel, &gContext); if (SUCCEEDED(status)) break; + + _tprintf(_T("D3D11CreateDevice returned [%d] for Driver Type %d\n"), status, DriverTypes[DriverTypeIndex]); } if (FAILED(status)) { _tprintf(_T("Failed to create device in InitializeDx\n")); - return 1; + //return 1; + + //debug + for (DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex) + { + status = D3D11CreateDevice(NULL, DriverTypes[DriverTypeIndex], NULL, NULL, FeatureLevels, NumFeatureLevels, + D3D11_SDK_VERSION, &gDevice, &FeatureLevel, &gContext); + if (SUCCEEDED(status)) + break; + + _tprintf(_T("D3D11CreateDevice returned [%d] for Driver Type %d\n"), status, DriverTypes[DriverTypeIndex]); + } + + if (FAILED(status)) + { + _tprintf(_T("Failed to create device in InitializeDx\n")); + return 1; + } } status = gDevice->lpVtbl->QueryInterface(gDevice, &IID_IDXGIDevice, (void**) &DxgiDevice); diff --git a/server/Windows/wf_rdpsnd.c b/server/Windows/wf_rdpsnd.c index 8ef5b2775..efdc5c960 100644 --- a/server/Windows/wf_rdpsnd.c +++ b/server/Windows/wf_rdpsnd.c @@ -41,7 +41,7 @@ IDirectSoundCapture8 * cap; IDirectSoundCaptureBuffer8* capBuf; DSCBUFFERDESC dscbd; -DWORD capturePos; +DWORD lastPos; #define BYTESPERSEC 176400 @@ -107,7 +107,7 @@ static void wf_peer_rdpsnd_activated(rdpsnd_server_context* context) context->SelectFormat(context, 4); context->SetVolume(context, 0x7FFF, 0x7FFF); - capturePos = 0; + lastPos = 0; CreateThread(NULL, 0, wf_rdpsnd_thread, latestPeer, 0, NULL); @@ -189,15 +189,24 @@ BOOL wf_peer_rdpsnd_init(wfPeerContext* context) DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam) { HRESULT hr; - DWORD beg, end; + DWORD beg = 0; + DWORD end = 0; DWORD diff, rate; wfPeerContext* context; wfInfo* wfi; + VOID* pbCaptureData = NULL; + DWORD dwCaptureLength = 0; + VOID* pbCaptureData2 = NULL; + DWORD dwCaptureLength2 = 0; + VOID* pbPlayData = NULL; + DWORD dwReadPos = 0; + LONG lLockSize = 0; + wfi = wf_info_get_instance(); context = (wfPeerContext*)lpParam; - rate = 1000 / 5; + rate = 1000 / 24; _tprintf(_T("Trying to start capture\n")); hr = capBuf->lpVtbl->Start(capBuf, DSCBSTART_LOOPING); @@ -209,13 +218,15 @@ DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam) while (1) { - VOID* pbCaptureData = NULL; - DWORD dwCaptureLength; - VOID* pbCaptureData2 = NULL; - DWORD dwCaptureLength2; - VOID* pbPlayData = NULL; - DWORD dwReadPos; - LONG lLockSize; + + end = GetTickCount(); + diff = end - beg; + + if (diff < rate) + { + Sleep(rate - diff); + } + beg = GetTickCount(); if (wf_rdpsnd_lock() > 0) @@ -235,9 +246,11 @@ DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam) break; } - lLockSize = dwReadPos - capturePos;//dscbd.dwBufferBytes; + lLockSize = dwReadPos - lastPos;//dscbd.dwBufferBytes; if (lLockSize < 0) lLockSize += dscbd.dwBufferBytes; + //printf("Last, read, lock = [%d, %d, %d]\n", lastPos, dwReadPos, lLockSize); + if (lLockSize == 0) { wf_rdpsnd_unlock(); @@ -245,7 +258,7 @@ DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam) } - hr = capBuf->lpVtbl->Lock(capBuf, capturePos, lLockSize, &pbCaptureData, &dwCaptureLength, &pbCaptureData2, &dwCaptureLength2, 0L); + hr = capBuf->lpVtbl->Lock(capBuf, lastPos, lLockSize, &pbCaptureData, &dwCaptureLength, &pbCaptureData2, &dwCaptureLength2, 0L); if (FAILED(hr)) { _tprintf(_T("Failed to lock sound capture buffer\n")); @@ -271,21 +284,15 @@ DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam) } //TODO keep track of location in buffer - capturePos += dwCaptureLength; - capturePos %= dscbd.dwBufferBytes; - capturePos += dwCaptureLength2; - capturePos %= dscbd.dwBufferBytes; + lastPos += dwCaptureLength; + lastPos %= dscbd.dwBufferBytes; + lastPos += dwCaptureLength2; + lastPos %= dscbd.dwBufferBytes; wf_rdpsnd_unlock(); } - end = GetTickCount(); - diff = end - beg; - - if (diff < rate) - { - Sleep(rate - diff); - } + } _tprintf(_T("Trying to stop sound capture\n")); @@ -295,7 +302,10 @@ DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam) _tprintf(_T("Failed to stop capture\n")); } _tprintf(_T("Capture stopped\n")); + capBuf->lpVtbl->Release(capBuf); + cap->lpVtbl->Release(cap); + lastPos = 0; return 0; } From 57a85450f6d0b5eb4198429cae445071a839608c Mon Sep 17 00:00:00 2001 From: Corey C Date: Tue, 16 Oct 2012 23:29:51 -0700 Subject: [PATCH 02/20] wfreerdp-server: more debug info --- server/Windows/wf_dxgi.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/server/Windows/wf_dxgi.c b/server/Windows/wf_dxgi.c index 6cfb8d90b..8ab5eed3f 100644 --- a/server/Windows/wf_dxgi.c +++ b/server/Windows/wf_dxgi.c @@ -81,7 +81,10 @@ int wf_dxgi_init(wfInfo* context) for (DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex) { - status = D3D11CreateDevice(NULL, DriverTypes[DriverTypeIndex], NULL, D3D11_CREATE_DEVICE_DEBUG, FeatureLevels, NumFeatureLevels, + /*status = D3D11CreateDevice(NULL, DriverTypes[DriverTypeIndex], NULL, D3D11_CREATE_DEVICE_DEBUG, FeatureLevels, NumFeatureLevels, + D3D11_SDK_VERSION, &gDevice, &FeatureLevel, &gContext); + */ + status = D3D11CreateDevice(NULL, DriverTypes[DriverTypeIndex], NULL, NULL, FeatureLevels, NumFeatureLevels, D3D11_SDK_VERSION, &gDevice, &FeatureLevel, &gContext); if (SUCCEEDED(status)) break; @@ -92,9 +95,10 @@ int wf_dxgi_init(wfInfo* context) if (FAILED(status)) { _tprintf(_T("Failed to create device in InitializeDx\n")); - //return 1; + return 1; //debug + /* for (DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex) { status = D3D11CreateDevice(NULL, DriverTypes[DriverTypeIndex], NULL, NULL, FeatureLevels, NumFeatureLevels, @@ -110,6 +114,7 @@ int wf_dxgi_init(wfInfo* context) _tprintf(_T("Failed to create device in InitializeDx\n")); return 1; } + */ } status = gDevice->lpVtbl->QueryInterface(gDevice, &IID_IDXGIDevice, (void**) &DxgiDevice); @@ -257,13 +262,13 @@ int wf_dxgi_nextFrame(wfInfo* wfi, UINT timeout) if (FAILED(status)) { - _tprintf(_T("Failed to acquire next frame\n")); + _tprintf(_T("Failed to acquire next frame with status=%d\n", status)); status = gOutputDuplication->lpVtbl->ReleaseFrame(gOutputDuplication); if (FAILED(status)) { - _tprintf(_T("Failed to release frame\n")); + _tprintf(_T("Failed to release frame with status=%d\n", status)); } return 1; From 9fbf1fb3763bc2560827ab3bc0c105000efd2faa Mon Sep 17 00:00:00 2001 From: Corey C Date: Wed, 17 Oct 2012 15:31:36 -0400 Subject: [PATCH 03/20] wfreerdp-server: fixed parenthesis error and added more debug output --- server/Windows/wf_dxgi.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/server/Windows/wf_dxgi.c b/server/Windows/wf_dxgi.c index 8ab5eed3f..b2662a286 100644 --- a/server/Windows/wf_dxgi.c +++ b/server/Windows/wf_dxgi.c @@ -236,7 +236,7 @@ int wf_dxgi_cleanup(wfInfo* wfi) int wf_dxgi_nextFrame(wfInfo* wfi, UINT timeout) { - HRESULT status; + HRESULT status = 0; UINT i = 0; UINT DataBufferSize = 0; BYTE* DataBuffer = NULL; @@ -262,7 +262,11 @@ int wf_dxgi_nextFrame(wfInfo* wfi, UINT timeout) if (FAILED(status)) { - _tprintf(_T("Failed to acquire next frame with status=%d\n", status)); + _tprintf(_T("Failed to acquire next frame with status=%#X\n"), status); + _tprintf(_T("\tAccumulated Frames: %d\n\tRects: %d\n\tBuffSize: %d\n"), + FrameInfo.AccumulatedFrames, + FrameInfo.RectsCoalesced, + FrameInfo.TotalMetadataBufferSize); status = gOutputDuplication->lpVtbl->ReleaseFrame(gOutputDuplication); From be080f8536868fd1f1d7acf9744e29a90dc03238 Mon Sep 17 00:00:00 2001 From: Corey C Date: Wed, 17 Oct 2012 16:17:19 -0400 Subject: [PATCH 04/20] wfreerdp-server: handle dxgi access lost error --- server/Windows/wf_dxgi.c | 78 ++++++++++++++++++++++++++++------------ server/Windows/wf_dxgi.h | 4 +++ 2 files changed, 60 insertions(+), 22 deletions(-) diff --git a/server/Windows/wf_dxgi.c b/server/Windows/wf_dxgi.c index b2662a286..133c94e36 100644 --- a/server/Windows/wf_dxgi.c +++ b/server/Windows/wf_dxgi.c @@ -67,18 +67,28 @@ DXGI_OUTDUPL_FRAME_INFO FrameInfo; int wf_dxgi_init(wfInfo* context) { - HRESULT status; - UINT dTop, i = 0; - DXGI_OUTPUT_DESC desc; - IDXGIOutput * pOutput; - UINT DriverTypeIndex; - IDXGIDevice* DxgiDevice = NULL; - IDXGIAdapter* DxgiAdapter = NULL; - IDXGIOutput* DxgiOutput = NULL; - IDXGIOutput1* DxgiOutput1 = NULL; - + //not sure if needed gAcquiredDesktopImage = NULL; + if (wf_dxgi_createDevice(context) != 0) + { + return 1; + } + + if (wf_dxgi_getDuplication(context) != 0) + { + return 1; + } + + return 0; + +} + +int wf_dxgi_createDevice(wfInfo* context) +{ + HRESULT status; + UINT DriverTypeIndex; + for (DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex) { /*status = D3D11CreateDevice(NULL, DriverTypes[DriverTypeIndex], NULL, D3D11_CREATE_DEVICE_DEBUG, FeatureLevels, NumFeatureLevels, @@ -116,7 +126,21 @@ int wf_dxgi_init(wfInfo* context) } */ } - + + return 0; +} + +int wf_dxgi_getDuplication(wfInfo* context) +{ + HRESULT status; + UINT dTop, i = 0; + DXGI_OUTPUT_DESC desc; + IDXGIOutput * pOutput; + IDXGIDevice* DxgiDevice = NULL; + IDXGIAdapter* DxgiAdapter = NULL; + IDXGIOutput* DxgiOutput = NULL; + IDXGIOutput1* DxgiOutput1 = NULL; + status = gDevice->lpVtbl->QueryInterface(gDevice, &IID_IDXGIDevice, (void**) &DxgiDevice); if (FAILED(status)) @@ -200,6 +224,7 @@ int wf_dxgi_init(wfInfo* context) return 0; } + int wf_dxgi_cleanup(wfInfo* wfi) { if (wfi->framesWaiting > 0) @@ -262,20 +287,29 @@ int wf_dxgi_nextFrame(wfInfo* wfi, UINT timeout) if (FAILED(status)) { - _tprintf(_T("Failed to acquire next frame with status=%#X\n"), status); - _tprintf(_T("\tAccumulated Frames: %d\n\tRects: %d\n\tBuffSize: %d\n"), - FrameInfo.AccumulatedFrames, - FrameInfo.RectsCoalesced, - FrameInfo.TotalMetadataBufferSize); - - status = gOutputDuplication->lpVtbl->ReleaseFrame(gOutputDuplication); - - if (FAILED(status)) + if (status == DXGI_ERROR_ACCESS_LOST) { - _tprintf(_T("Failed to release frame with status=%d\n", status)); + _tprintf(_T("Failed to acquire next frame with status=%#X\n"), status); + _tprintf(_T("Trying to reinitialize due to ACCESS LOST...")); + wf_dxgi_getDuplication(wfi); } + else + { + _tprintf(_T("Failed to acquire next frame with status=%#X\n"), status); + _tprintf(_T("\tAccumulated Frames: %d\n\tRects: %d\n\tBuffSize: %d\n"), + FrameInfo.AccumulatedFrames, + FrameInfo.RectsCoalesced, + FrameInfo.TotalMetadataBufferSize); + + status = gOutputDuplication->lpVtbl->ReleaseFrame(gOutputDuplication); + + if (FAILED(status)) + { + _tprintf(_T("Failed to release frame with status=%d\n", status)); + } - return 1; + return 1; + } } status = DesktopResource->lpVtbl->QueryInterface(DesktopResource, &IID_ID3D11Texture2D, (void**) &gAcquiredDesktopImage); diff --git a/server/Windows/wf_dxgi.h b/server/Windows/wf_dxgi.h index c7b73b803..1f47ee3a8 100644 --- a/server/Windows/wf_dxgi.h +++ b/server/Windows/wf_dxgi.h @@ -24,6 +24,10 @@ int wf_dxgi_init(wfInfo* context); +int wf_dxgi_createDevice(wfInfo* context); + +int wf_dxgi_getDuplication(wfInfo* context); + int wf_dxgi_cleanup(wfInfo* context); int wf_dxgi_nextFrame(wfInfo* context, UINT timeout); From 38f4541fde9e93f856d27025b714245f27e373cb Mon Sep 17 00:00:00 2001 From: Corey C Date: Wed, 17 Oct 2012 16:50:39 -0400 Subject: [PATCH 05/20] wfreerdp-server: release duplication --- server/Windows/wf_dxgi.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/server/Windows/wf_dxgi.c b/server/Windows/wf_dxgi.c index 133c94e36..a0ef7f52f 100644 --- a/server/Windows/wf_dxgi.c +++ b/server/Windows/wf_dxgi.c @@ -217,7 +217,7 @@ int wf_dxgi_getDuplication(wfInfo* context) return 1; } - _tprintf(_T("Failed to get duplicate output\n")); + _tprintf(_T("Failed to get duplicate output. Status = %#X\n"), status); return 1; } @@ -291,7 +291,22 @@ int wf_dxgi_nextFrame(wfInfo* wfi, UINT timeout) { _tprintf(_T("Failed to acquire next frame with status=%#X\n"), status); _tprintf(_T("Trying to reinitialize due to ACCESS LOST...")); + if (gAcquiredDesktopImage) + { + + gAcquiredDesktopImage->lpVtbl->Release(gAcquiredDesktopImage); + gAcquiredDesktopImage = NULL; + } + + if (gOutputDuplication) + { + gOutputDuplication->lpVtbl->Release(gOutputDuplication); + gOutputDuplication = NULL; + } + wf_dxgi_getDuplication(wfi); + + return 1; } else { From 0d7414fb613913fdf93f676018a9ca40de3b5da4 Mon Sep 17 00:00:00 2001 From: Corey C Date: Wed, 17 Oct 2012 17:06:03 -0400 Subject: [PATCH 06/20] wfreerdp-server: fixed debug prints --- server/Windows/wf_dxgi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/Windows/wf_dxgi.c b/server/Windows/wf_dxgi.c index a0ef7f52f..bef369f6f 100644 --- a/server/Windows/wf_dxgi.c +++ b/server/Windows/wf_dxgi.c @@ -311,16 +311,16 @@ int wf_dxgi_nextFrame(wfInfo* wfi, UINT timeout) else { _tprintf(_T("Failed to acquire next frame with status=%#X\n"), status); - _tprintf(_T("\tAccumulated Frames: %d\n\tRects: %d\n\tBuffSize: %d\n"), + /*_tprintf(_T("\tAccumulated Frames: %d\n\tRects: %d\n\tBuffSize: %d\n"), FrameInfo.AccumulatedFrames, FrameInfo.RectsCoalesced, - FrameInfo.TotalMetadataBufferSize); + FrameInfo.TotalMetadataBufferSize);*/ status = gOutputDuplication->lpVtbl->ReleaseFrame(gOutputDuplication); if (FAILED(status)) { - _tprintf(_T("Failed to release frame with status=%d\n", status)); + _tprintf(_T("Failed to release frame with status=%d\n"), status); } return 1; From 5f713c6b9c357f46fa47a424f941ff923002a39a Mon Sep 17 00:00:00 2001 From: Corey C Date: Wed, 17 Oct 2012 18:39:04 -0400 Subject: [PATCH 07/20] wfreerdp-server: fixed 2 bugs First a bug where in the case that on windows 8, there is only a mouse pointer update, the frame does not get released. Second an incorrect timeout value was being passed. --- server/Windows/wf_dxgi.c | 10 ++++++++++ server/Windows/wf_info.c | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/server/Windows/wf_dxgi.c b/server/Windows/wf_dxgi.c index bef369f6f..39ec71a21 100644 --- a/server/Windows/wf_dxgi.c +++ b/server/Windows/wf_dxgi.c @@ -338,6 +338,16 @@ int wf_dxgi_nextFrame(wfInfo* wfi, UINT timeout) wfi->framesWaiting = FrameInfo.AccumulatedFrames; + if (FrameInfo.AccumulatedFrames == 0) + { + status = gOutputDuplication->lpVtbl->ReleaseFrame(gOutputDuplication); + + if (FAILED(status)) + { + _tprintf(_T("Failed to release frame with status=%d\n"), status); + } + } + return 0; } diff --git a/server/Windows/wf_info.c b/server/Windows/wf_info.c index 5974f98d8..fe0ff25a4 100644 --- a/server/Windows/wf_info.c +++ b/server/Windows/wf_info.c @@ -282,7 +282,7 @@ BOOL wf_info_have_updates(wfInfo* wfi) void wf_info_update_changes(wfInfo* wfi) { #ifdef WITH_WIN8 - wf_dxgi_nextFrame(wfi, wfi->framesPerSecond / 1000); + wf_dxgi_nextFrame(wfi, wfi->framesPerSecond * 1000); #else GETCHANGESBUF* buf; From f855987b44e021b7aeaf52dc728d7a78c9362208 Mon Sep 17 00:00:00 2001 From: C-o-r-E Date: Fri, 19 Oct 2012 17:29:44 -0400 Subject: [PATCH 08/20] wfreerdp-server: win7 guid fix --- server/Windows/wf_interface.h | 1 + server/Windows/wf_rdpsnd.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/server/Windows/wf_interface.h b/server/Windows/wf_interface.h index e7400010c..93674874a 100644 --- a/server/Windows/wf_interface.h +++ b/server/Windows/wf_interface.h @@ -29,6 +29,7 @@ #include #include + #include #define WF_SRV_CALLBACK_EVENT_CONNECT 1 diff --git a/server/Windows/wf_rdpsnd.c b/server/Windows/wf_rdpsnd.c index efdc5c960..bc7039a32 100644 --- a/server/Windows/wf_rdpsnd.c +++ b/server/Windows/wf_rdpsnd.c @@ -25,6 +25,8 @@ #include #include + +#include #define CINTERFACE #include #include From 165b18d0711eefd1fe42c76ca97ebca98f86a769 Mon Sep 17 00:00:00 2001 From: Corey C Date: Mon, 22 Oct 2012 18:43:37 -0400 Subject: [PATCH 09/20] wfreerdp-server: code cleanup --- server/Windows/wf_dxgi.c | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/server/Windows/wf_dxgi.c b/server/Windows/wf_dxgi.c index 8fc5c8cc7..3b71905ae 100644 --- a/server/Windows/wf_dxgi.c +++ b/server/Windows/wf_dxgi.c @@ -91,10 +91,7 @@ int wf_dxgi_createDevice(wfInfo* context) for (DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex) { - /*status = D3D11CreateDevice(NULL, DriverTypes[DriverTypeIndex], NULL, D3D11_CREATE_DEVICE_DEBUG, FeatureLevels, NumFeatureLevels, - D3D11_SDK_VERSION, &gDevice, &FeatureLevel, &gContext); - */ - status = D3D11CreateDevice(NULL, DriverTypes[DriverTypeIndex], NULL, NULL, FeatureLevels, NumFeatureLevels, + status = D3D11CreateDevice(NULL, DriverTypes[DriverTypeIndex], NULL, 0, FeatureLevels, NumFeatureLevels, D3D11_SDK_VERSION, &gDevice, &FeatureLevel, &gContext); if (SUCCEEDED(status)) break; @@ -106,25 +103,6 @@ int wf_dxgi_createDevice(wfInfo* context) { _tprintf(_T("Failed to create device in InitializeDx\n")); return 1; - - //debug - /* - for (DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex) - { - status = D3D11CreateDevice(NULL, DriverTypes[DriverTypeIndex], NULL, NULL, FeatureLevels, NumFeatureLevels, - D3D11_SDK_VERSION, &gDevice, &FeatureLevel, &gContext); - if (SUCCEEDED(status)) - break; - - _tprintf(_T("D3D11CreateDevice returned [%d] for Driver Type %d\n"), status, DriverTypes[DriverTypeIndex]); - } - - if (FAILED(status)) - { - _tprintf(_T("Failed to create device in InitializeDx\n")); - return 1; - } - */ } return 0; @@ -310,10 +288,6 @@ int wf_dxgi_nextFrame(wfInfo* wfi, UINT timeout) else { _tprintf(_T("Failed to acquire next frame with status=%#X\n"), status); - /*_tprintf(_T("\tAccumulated Frames: %d\n\tRects: %d\n\tBuffSize: %d\n"), - FrameInfo.AccumulatedFrames, - FrameInfo.RectsCoalesced, - FrameInfo.TotalMetadataBufferSize);*/ status = gOutputDuplication->lpVtbl->ReleaseFrame(gOutputDuplication); From a53dfae1ddcefbc13a153b25f6752da5687edec8 Mon Sep 17 00:00:00 2001 From: Corey C Date: Tue, 23 Oct 2012 18:49:03 -0400 Subject: [PATCH 10/20] wfreerdp-server: added ability to list displays --- server/Windows/cli/wfreerdp.c | 11 +++++++++++ server/Windows/wf_interface.c | 21 +++++++++++++++++++++ server/Windows/wf_interface.h | 2 ++ 3 files changed, 34 insertions(+) diff --git a/server/Windows/cli/wfreerdp.c b/server/Windows/cli/wfreerdp.c index b40e796de..eda7f30ae 100644 --- a/server/Windows/cli/wfreerdp.c +++ b/server/Windows/cli/wfreerdp.c @@ -34,10 +34,21 @@ int main(int argc, char* argv[]) { + int index; wfServer* server; server = wfreerdp_server_new(); + //handle args + index = 1; + //first the args that will cause the program to terminate + if (strcmp("--list-screens", argv[index]) == 0) + { + printf("Detecting screens...\n"); + get_screen_info(); + return 0; + } + if (argc == 2) server->port = (DWORD) atoi(argv[1]); diff --git a/server/Windows/wf_interface.c b/server/Windows/wf_interface.c index fc5512a79..f066eae45 100644 --- a/server/Windows/wf_interface.c +++ b/server/Windows/wf_interface.c @@ -36,6 +36,27 @@ cbCallback cbEvent; +void get_screen_info() +{ + int i; + DISPLAY_DEVICE dd; + + memset(&dd, 0, sizeof(DISPLAY_DEVICE)); + dd.cb = sizeof(DISPLAY_DEVICE); + + for (i=0; ; i++) + { + if (EnumDisplayDevices(NULL, i, &dd, 0) != 0) + { + _tprintf(_T("%d) [%d] [%s] [%s]\n"), i, dd.DeviceID, dd.DeviceName, dd.DeviceString); + } + else + { + break; + } + } +} + DWORD WINAPI wf_server_main_loop(LPVOID lpParam) { int i, fds; diff --git a/server/Windows/wf_interface.h b/server/Windows/wf_interface.h index 93674874a..bfa667d23 100644 --- a/server/Windows/wf_interface.h +++ b/server/Windows/wf_interface.h @@ -102,6 +102,8 @@ typedef struct wf_server wfServer; typedef void (__stdcall* cbCallback) (int, UINT32); +FREERDP_API void get_screen_info(); + FREERDP_API BOOL wfreerdp_server_start(wfServer* server); FREERDP_API BOOL wfreerdp_server_stop(wfServer* server); From baf984314456b061f396ecadd14890416f6aa7ce Mon Sep 17 00:00:00 2001 From: Corey C Date: Tue, 23 Oct 2012 19:41:50 -0400 Subject: [PATCH 11/20] wfreerdp-server: added screen info api --- server/Windows/cli/wfreerdp.c | 26 ++++++++++++++++++++++++-- server/Windows/wf_interface.c | 28 +++++++++++++++++----------- server/Windows/wf_interface.h | 2 +- 3 files changed, 42 insertions(+), 14 deletions(-) diff --git a/server/Windows/cli/wfreerdp.c b/server/Windows/cli/wfreerdp.c index eda7f30ae..1a1b2ea5d 100644 --- a/server/Windows/cli/wfreerdp.c +++ b/server/Windows/cli/wfreerdp.c @@ -44,8 +44,30 @@ int main(int argc, char* argv[]) //first the args that will cause the program to terminate if (strcmp("--list-screens", argv[index]) == 0) { - printf("Detecting screens...\n"); - get_screen_info(); + _TCHAR name[32]; + int width; + int height; + int bpp; + int i; + + _tprintf(_T("Detecting screens...\n")); + _tprintf(_T("ID\tName\tResolution\n")); + + for (i=0; ; i++) + { + if (get_screen_info(i, name, &width, &height, &bpp) != 0) + { + if ( (width * height * bpp) == 0 ) + continue; + + _tprintf(_T("%d\t%s\t"), i, name); + _tprintf(_T("%dx%dx%d\n"), width, height, bpp); + } + else + { + break; + } + } return 0; } diff --git a/server/Windows/wf_interface.c b/server/Windows/wf_interface.c index f066eae45..824791913 100644 --- a/server/Windows/wf_interface.c +++ b/server/Windows/wf_interface.c @@ -36,25 +36,31 @@ cbCallback cbEvent; -void get_screen_info() +int get_screen_info(int id, _TCHAR* name, int* width, int* height, int* bpp) { - int i; DISPLAY_DEVICE dd; memset(&dd, 0, sizeof(DISPLAY_DEVICE)); dd.cb = sizeof(DISPLAY_DEVICE); - for (i=0; ; i++) + if (EnumDisplayDevices(NULL, id, &dd, 0) != 0) { - if (EnumDisplayDevices(NULL, i, &dd, 0) != 0) - { - _tprintf(_T("%d) [%d] [%s] [%s]\n"), i, dd.DeviceID, dd.DeviceName, dd.DeviceString); - } - else - { - break; - } + HDC dc; + + _tcscpy(name, dd.DeviceName); + dc = CreateDC(NULL, dd.DeviceName, NULL, NULL); + *width = GetDeviceCaps(dc, HORZRES); + *height = GetDeviceCaps(dc, VERTRES); + *bpp = GetDeviceCaps(dc, BITSPIXEL); + ReleaseDC(NULL, dc); + } + else + { + return 0; + } + + return 1; } DWORD WINAPI wf_server_main_loop(LPVOID lpParam) diff --git a/server/Windows/wf_interface.h b/server/Windows/wf_interface.h index bfa667d23..80c31d0c0 100644 --- a/server/Windows/wf_interface.h +++ b/server/Windows/wf_interface.h @@ -102,7 +102,7 @@ typedef struct wf_server wfServer; typedef void (__stdcall* cbCallback) (int, UINT32); -FREERDP_API void get_screen_info(); +FREERDP_API int get_screen_info(int id, _TCHAR* name, int* w, int* h, int* b); FREERDP_API BOOL wfreerdp_server_start(wfServer* server); FREERDP_API BOOL wfreerdp_server_stop(wfServer* server); From 94ea05cb57d24ded0566971a06d7b3fa54114d85 Mon Sep 17 00:00:00 2001 From: Corey C Date: Tue, 23 Oct 2012 20:32:29 -0400 Subject: [PATCH 12/20] wfreerdp-server: initial cli multimon support --- server/Windows/cli/wfreerdp.c | 67 ++++++++++++++++++++++------------- server/Windows/wf_dxgi.c | 2 +- server/Windows/wf_interface.c | 14 +++++++- server/Windows/wf_interface.h | 2 ++ server/Windows/wf_peer.c | 9 ++++- 5 files changed, 66 insertions(+), 28 deletions(-) diff --git a/server/Windows/cli/wfreerdp.c b/server/Windows/cli/wfreerdp.c index 1a1b2ea5d..edc47dd0c 100644 --- a/server/Windows/cli/wfreerdp.c +++ b/server/Windows/cli/wfreerdp.c @@ -41,38 +41,55 @@ int main(int argc, char* argv[]) //handle args index = 1; - //first the args that will cause the program to terminate - if (strcmp("--list-screens", argv[index]) == 0) + while (index < argc) { - _TCHAR name[32]; - int width; - int height; - int bpp; - int i; - - _tprintf(_T("Detecting screens...\n")); - _tprintf(_T("ID\tName\tResolution\n")); - - for (i=0; ; i++) + //first the args that will cause the program to terminate + if (strcmp("--list-screens", argv[index]) == 0) { - if (get_screen_info(i, name, &width, &height, &bpp) != 0) - { - if ( (width * height * bpp) == 0 ) - continue; + _TCHAR name[32]; + int width; + int height; + int bpp; + int i; - _tprintf(_T("%d\t%s\t"), i, name); - _tprintf(_T("%dx%dx%d\n"), width, height, bpp); - } - else + _tprintf(_T("Detecting screens...\n")); + _tprintf(_T("ID\tName\tResolution\n")); + + for (i=0; ; i++) { - break; + if (get_screen_info(i, name, &width, &height, &bpp) != 0) + { + if ( (width * height * bpp) == 0 ) + continue; + + _tprintf(_T("%d\t%s\t"), i, name); + _tprintf(_T("%dx%dx%d\n"), width, height, bpp); + } + else + { + break; + } } + return 0; } - return 0; - } + + if (strcmp("--screen", argv[index]) == 0) + { + index++; + if (index == argc) + { + printf("missing screen id parameter\n"); + return 0; + } - if (argc == 2) - server->port = (DWORD) atoi(argv[1]); + set_screen_id(atoi(argv[index])); + index++; + } + + + if (index == argc - 1) + server->port = (DWORD) atoi(argv[index]); + } printf("Starting server\n"); diff --git a/server/Windows/wf_dxgi.c b/server/Windows/wf_dxgi.c index 3b71905ae..ac9b4b907 100644 --- a/server/Windows/wf_dxgi.c +++ b/server/Windows/wf_dxgi.c @@ -161,7 +161,7 @@ int wf_dxgi_getDuplication(wfInfo* context) ++i; } - dTop = 0; + dTop = context->screenID; status = DxgiAdapter->lpVtbl->EnumOutputs(DxgiAdapter, dTop, &DxgiOutput); DxgiAdapter->lpVtbl->Release(DxgiAdapter); diff --git a/server/Windows/wf_interface.c b/server/Windows/wf_interface.c index 824791913..eb89763be 100644 --- a/server/Windows/wf_interface.c +++ b/server/Windows/wf_interface.c @@ -47,7 +47,9 @@ int get_screen_info(int id, _TCHAR* name, int* width, int* height, int* bpp) { HDC dc; - _tcscpy(name, dd.DeviceName); + if (name != NULL) + _tcscpy(name, dd.DeviceName); + dc = CreateDC(NULL, dd.DeviceName, NULL, NULL); *width = GetDeviceCaps(dc, HORZRES); *height = GetDeviceCaps(dc, VERTRES); @@ -63,6 +65,16 @@ int get_screen_info(int id, _TCHAR* name, int* width, int* height, int* bpp) return 1; } +void set_screen_id(int id) +{ + wfInfo* wfi; + + wfi = wf_info_get_instance(); + wfi->screenID = id; + + return; +} + DWORD WINAPI wf_server_main_loop(LPVOID lpParam) { int i, fds; diff --git a/server/Windows/wf_interface.h b/server/Windows/wf_interface.h index 80c31d0c0..677c6efce 100644 --- a/server/Windows/wf_interface.h +++ b/server/Windows/wf_interface.h @@ -74,6 +74,7 @@ struct wf_info BOOL input_disabled; BOOL force_all_disconnect; + int screenID; }; struct wf_peer_context @@ -103,6 +104,7 @@ typedef struct wf_server wfServer; typedef void (__stdcall* cbCallback) (int, UINT32); FREERDP_API int get_screen_info(int id, _TCHAR* name, int* w, int* h, int* b); +FREERDP_API void set_screen_id(int id); FREERDP_API BOOL wfreerdp_server_start(wfServer* server); FREERDP_API BOOL wfreerdp_server_stop(wfServer* server); diff --git a/server/Windows/wf_peer.c b/server/Windows/wf_peer.c index c0216114c..7ef0b850b 100644 --- a/server/Windows/wf_peer.c +++ b/server/Windows/wf_peer.c @@ -82,11 +82,18 @@ BOOL wf_peer_post_connect(freerdp_peer* client) wfi = context->info; settings = client->settings; - hdc = GetDC(NULL); + /*hdc = GetDC(NULL); wfi->width = GetDeviceCaps(hdc, HORZRES); wfi->height = GetDeviceCaps(hdc, VERTRES); wfi->bitsPerPixel = GetDeviceCaps(hdc, BITSPIXEL); ReleaseDC(NULL, hdc); + */ + + if (get_screen_info(wfi->screenID, NULL, &wfi->width, &wfi->height, &wfi->bitsPerPixel) == 0) + { + _tprintf(_T("postconnect: error getting screen info for screen %d\n"), wfi->screenID); + return FALSE; + } if ((settings->width != wfi->width) || (settings->height != wfi->height)) { From 7f2dcf3257323bc8e79c7b6d4fdf3eabbdbf8be8 Mon Sep 17 00:00:00 2001 From: Corey C Date: Tue, 23 Oct 2012 20:43:39 -0400 Subject: [PATCH 13/20] wfreerdp-server: fixed crash with selected zero resolution displays --- server/Windows/wf_peer.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/server/Windows/wf_peer.c b/server/Windows/wf_peer.c index 7ef0b850b..b0ae53490 100644 --- a/server/Windows/wf_peer.c +++ b/server/Windows/wf_peer.c @@ -89,7 +89,11 @@ BOOL wf_peer_post_connect(freerdp_peer* client) ReleaseDC(NULL, hdc); */ - if (get_screen_info(wfi->screenID, NULL, &wfi->width, &wfi->height, &wfi->bitsPerPixel) == 0) + if ( + (get_screen_info(wfi->screenID, NULL, &wfi->width, &wfi->height, &wfi->bitsPerPixel) == 0) || + (wfi->width == 0) || + (wfi->height == 0) || + (wfi->bitsPerPixel == 0) ) { _tprintf(_T("postconnect: error getting screen info for screen %d\n"), wfi->screenID); return FALSE; From a88dbb6b85acf464b8d13d2880d4c383f4be33d6 Mon Sep 17 00:00:00 2001 From: C-o-r-E Date: Thu, 25 Oct 2012 15:25:55 -0400 Subject: [PATCH 14/20] wfreerdp-server: added more info for screen list --- server/Windows/cli/wfreerdp.c | 8 ++++---- server/Windows/wf_interface.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/server/Windows/cli/wfreerdp.c b/server/Windows/cli/wfreerdp.c index edc47dd0c..f7144ecc7 100644 --- a/server/Windows/cli/wfreerdp.c +++ b/server/Windows/cli/wfreerdp.c @@ -46,14 +46,14 @@ int main(int argc, char* argv[]) //first the args that will cause the program to terminate if (strcmp("--list-screens", argv[index]) == 0) { - _TCHAR name[32]; + _TCHAR name[128]; int width; int height; int bpp; int i; _tprintf(_T("Detecting screens...\n")); - _tprintf(_T("ID\tName\tResolution\n")); + _tprintf(_T("\nID\tResolution\t\tName (Interface)\n\n")); for (i=0; ; i++) { @@ -62,8 +62,8 @@ int main(int argc, char* argv[]) if ( (width * height * bpp) == 0 ) continue; - _tprintf(_T("%d\t%s\t"), i, name); - _tprintf(_T("%dx%dx%d\n"), width, height, bpp); + _tprintf(_T("%d\t%dx%dx%d\t"), i, width, height, bpp); + _tprintf(_T("%s\n"), name); } else { diff --git a/server/Windows/wf_interface.c b/server/Windows/wf_interface.c index eb89763be..79030f18a 100644 --- a/server/Windows/wf_interface.c +++ b/server/Windows/wf_interface.c @@ -48,7 +48,7 @@ int get_screen_info(int id, _TCHAR* name, int* width, int* height, int* bpp) HDC dc; if (name != NULL) - _tcscpy(name, dd.DeviceName); + _stprintf(name, _T("%s (%s)"), dd.DeviceName, dd.DeviceString); dc = CreateDC(NULL, dd.DeviceName, NULL, NULL); *width = GetDeviceCaps(dc, HORZRES); From 32ebeb44707e1093840c54e85965eec20b233b4f Mon Sep 17 00:00:00 2001 From: C-o-r-E Date: Tue, 30 Oct 2012 19:43:51 -0400 Subject: [PATCH 15/20] wfreerdp-server: fix arg parsing --- server/Windows/cli/wfreerdp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/Windows/cli/wfreerdp.c b/server/Windows/cli/wfreerdp.c index f7144ecc7..503247aa7 100644 --- a/server/Windows/cli/wfreerdp.c +++ b/server/Windows/cli/wfreerdp.c @@ -88,7 +88,10 @@ int main(int argc, char* argv[]) if (index == argc - 1) + { server->port = (DWORD) atoi(argv[index]); + break; + } } printf("Starting server\n"); From 4841b05008a61a602e025930d60c27590d42e022 Mon Sep 17 00:00:00 2001 From: C-o-r-E Date: Wed, 31 Oct 2012 17:24:14 -0400 Subject: [PATCH 16/20] wfreerdp-server: refactored monitor related data structures --- server/Windows/cli/wfreerdp.c | 22 +++++++++++ server/Windows/wf_info.c | 14 +++---- server/Windows/wf_interface.h | 15 +++++-- server/Windows/wf_mirage.c | 73 +++++++++++++++++++---------------- server/Windows/wf_mirage.h | 10 ++--- server/Windows/wf_peer.c | 22 ++++------- server/Windows/wf_update.c | 4 +- 7 files changed, 95 insertions(+), 65 deletions(-) diff --git a/server/Windows/cli/wfreerdp.c b/server/Windows/cli/wfreerdp.c index 503247aa7..0b855becd 100644 --- a/server/Windows/cli/wfreerdp.c +++ b/server/Windows/cli/wfreerdp.c @@ -32,6 +32,22 @@ #include "wfreerdp.h" +int IDcount = 0; + +BOOL CALLBACK moncb(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) +{ + + printf("%d\t(%d, %d), (%d, %d)\n", + IDcount, + lprcMonitor->left, + lprcMonitor->top, + lprcMonitor->right, + lprcMonitor->bottom); + + + IDcount++; +} + int main(int argc, char* argv[]) { int index; @@ -70,6 +86,12 @@ int main(int argc, char* argv[]) break; } } + + { + printf("\n"); + EnumDisplayMonitors(NULL, NULL, moncb, NULL); + } + return 0; } diff --git a/server/Windows/wf_info.c b/server/Windows/wf_info.c index fe0ff25a4..e36a9f222 100644 --- a/server/Windows/wf_info.c +++ b/server/Windows/wf_info.c @@ -313,11 +313,11 @@ void wf_info_find_invalid_region(wfInfo* wfi) if (wfi->invalid.top < 0) wfi->invalid.top = 0; - if (wfi->invalid.right >= wfi->width) - wfi->invalid.right = wfi->width - 1; + if (wfi->invalid.right >= wfi->servscreen_width) + wfi->invalid.right = wfi->servscreen_width - 1; - if (wfi->invalid.bottom >= wfi->height) - wfi->invalid.bottom = wfi->height - 1; + if (wfi->invalid.bottom >= wfi->servscreen_height) + wfi->invalid.bottom = wfi->servscreen_height - 1; } void wf_info_clear_invalid_region(wfInfo* wfi) @@ -328,7 +328,7 @@ void wf_info_clear_invalid_region(wfInfo* wfi) void wf_info_invalidate_full_screen(wfInfo* wfi) { - SetRect(&wfi->invalid, 0, 0, wfi->width, wfi->height); + SetRect(&wfi->invalid, 0, 0, wfi->servscreen_width, wfi->servscreen_height); } BOOL wf_info_have_invalid_region(wfInfo* wfi) @@ -352,9 +352,9 @@ void wf_info_getScreenData(wfInfo* wfi, long* width, long* height, BYTE** pBits, *width += 1; *height += 1; - offset = (4 * wfi->invalid.left) + (wfi->invalid.top * wfi->width * 4); + offset = (4 * wfi->invalid.left) + (wfi->invalid.top * wfi->servscreen_width * 4); *pBits = ((BYTE*) (changes->Userbuffer)) + offset; - *pitch = wfi->width * 4; + *pitch = wfi->servscreen_width * 4; } #endif } diff --git a/server/Windows/wf_interface.h b/server/Windows/wf_interface.h index 677c6efce..83819eac0 100644 --- a/server/Windows/wf_interface.h +++ b/server/Windows/wf_interface.h @@ -43,8 +43,18 @@ typedef struct wf_peer_context wfPeerContext; struct wf_info { STREAM* s; - int width; - int height; + + //screen and monitor info + int screenID; + int virtscreen_width; + int virtscreen_height; + int servscreen_width; + int servscreen_height; + int servscreen_xoffset; + int servscreen_yoffset; + //int width; + //int height; + int frame_idx; int bitsPerPixel; HDC driverDC; @@ -74,7 +84,6 @@ struct wf_info BOOL input_disabled; BOOL force_all_disconnect; - int screenID; }; struct wf_peer_context diff --git a/server/Windows/wf_mirage.c b/server/Windows/wf_mirage.c index 150a5caae..2b2b4a71e 100644 --- a/server/Windows/wf_mirage.c +++ b/server/Windows/wf_mirage.c @@ -26,10 +26,10 @@ /* This function will iterate over the loaded display devices until it finds the mirror device we want to load. If found, it will then copy the registry -key corresponding to the device to the context and returns TRUE. Otherwise +key corresponding to the device to the wfi and returns TRUE. Otherwise the function returns FALSE. */ -BOOL wf_mirror_driver_find_display_device(wfInfo* context) +BOOL wf_mirror_driver_find_display_device(wfInfo* wfi) { BOOL result; BOOL devFound; @@ -52,13 +52,13 @@ BOOL wf_mirror_driver_find_display_device(wfInfo* context) if (_tcsncmp(deviceInfo.DeviceKey, DEVICE_KEY_PREFIX, deviceKeyPrefixLength) == 0) { deviceKeyLength = _tcslen(deviceInfo.DeviceKey) - deviceKeyPrefixLength; - context->deviceKey = (LPTSTR) malloc((deviceKeyLength + 1) * sizeof(TCHAR)); + wfi->deviceKey = (LPTSTR) malloc((deviceKeyLength + 1) * sizeof(TCHAR)); - _tcsncpy_s(context->deviceKey, deviceKeyLength + 1, + _tcsncpy_s(wfi->deviceKey, deviceKeyLength + 1, &deviceInfo.DeviceKey[deviceKeyPrefixLength], deviceKeyLength); } - _tcsncpy_s(context->deviceName, 32, deviceInfo.DeviceName, _tcslen(deviceInfo.DeviceName)); + _tcsncpy_s(wfi->deviceName, 32, deviceInfo.DeviceName, _tcslen(deviceInfo.DeviceName)); return TRUE; } @@ -70,7 +70,7 @@ BOOL wf_mirror_driver_find_display_device(wfInfo* context) /** * This function will attempt to access the the windows registry using the device - * key stored in the current context. It will attempt to read the value of the + * key stored in the current wfi. It will attempt to read the value of the * "Attach.ToDesktop" subkey and will return TRUE if the value is already set to * val. If unable to read the subkey, this function will return FALSE. If the * subkey is not set to val it will then attempt to set it to val and return TRUE. If @@ -78,7 +78,7 @@ BOOL wf_mirror_driver_find_display_device(wfInfo* context) * FALSE. */ -BOOL wf_mirror_driver_display_device_attach(wfInfo* context, DWORD mode) +BOOL wf_mirror_driver_display_device_attach(wfInfo* wfi, DWORD mode) { HKEY hKey; LONG status; @@ -86,7 +86,7 @@ BOOL wf_mirror_driver_display_device_attach(wfInfo* context, DWORD mode) DWORD dwSize; DWORD dwValue; - status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, context->deviceKey, + status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, wfi->deviceKey, 0, KEY_READ | KEY_WOW64_64KEY, &hKey); if (status != ERROR_SUCCESS) @@ -170,7 +170,7 @@ void wf_mirror_driver_print_display_change_status(LONG status) * If unload is nonzero then the the driver will be asked to remove itself. */ -BOOL wf_mirror_driver_update(wfInfo* context, int unload) +BOOL wf_mirror_driver_update(wfInfo* wfi, int unload) { HDC dc; BOOL status; @@ -182,20 +182,27 @@ BOOL wf_mirror_driver_update(wfInfo* context, int unload) if (!unload) { + int vscreen_w; + int vscreen_h; + //first let's get the virtual screen dimentions + vscreen_w = GetSystemMetrics(SM_CXVIRTUALSCREEN); + vscreen_h = GetSystemMetrics(SM_CYVIRTUALSCREEN); + /* * Will have to come back to this for supporting non primary displays and multimonitor setups */ dc = GetDC(NULL); - context->width = GetDeviceCaps(dc, HORZRES); - context->height = GetDeviceCaps(dc, VERTRES); - context->bitsPerPixel = GetDeviceCaps(dc, BITSPIXEL); + wfi->servscreen_width = GetDeviceCaps(dc, HORZRES); + wfi->servscreen_height = GetDeviceCaps(dc, VERTRES); + wfi->bitsPerPixel = GetDeviceCaps(dc, BITSPIXEL); ReleaseDC(NULL, dc); + } else { - context->width = 0; - context->height = 0; - context->bitsPerPixel = 0; + wfi->servscreen_width = 0; + wfi->servscreen_height = 0; + wfi->bitsPerPixel = 0; } deviceMode = (DEVMODE*) malloc(sizeof(DEVMODE) + EXT_DEVMODE_SIZE_MAX); @@ -210,17 +217,17 @@ BOOL wf_mirror_driver_update(wfInfo* context, int unload) deviceMode->dmSize = sizeof(DEVMODE); deviceMode->dmDriverExtra = drvExtraSaved; - deviceMode->dmPelsWidth = context->width; - deviceMode->dmPelsHeight = context->height; - deviceMode->dmBitsPerPel = context->bitsPerPixel; + deviceMode->dmPelsWidth = wfi->servscreen_width; + deviceMode->dmPelsHeight = wfi->servscreen_height; + deviceMode->dmBitsPerPel = wfi->bitsPerPixel; deviceMode->dmPosition.x = 0; deviceMode->dmPosition.y = 0; deviceMode->dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_POSITION; - _tcsncpy_s(deviceMode->dmDeviceName, 32, context->deviceName, _tcslen(context->deviceName)); + _tcsncpy_s(deviceMode->dmDeviceName, 32, wfi->deviceName, _tcslen(wfi->deviceName)); - disp_change_status = ChangeDisplaySettingsEx(context->deviceName, deviceMode, NULL, CDS_UPDATEREGISTRY, NULL); + disp_change_status = ChangeDisplaySettingsEx(wfi->deviceName, deviceMode, NULL, CDS_UPDATEREGISTRY, NULL); status = (disp_change_status == DISP_CHANGE_SUCCESSFUL) ? TRUE : FALSE; @@ -230,50 +237,50 @@ BOOL wf_mirror_driver_update(wfInfo* context, int unload) return status; } -BOOL wf_mirror_driver_map_memory(wfInfo* context) +BOOL wf_mirror_driver_map_memory(wfInfo* wfi) { int status; GETCHANGESBUF* b; - context->driverDC = CreateDC(context->deviceName, NULL, NULL, NULL); + wfi->driverDC = CreateDC(wfi->deviceName, NULL, NULL, NULL); - if (context->driverDC == NULL) + if (wfi->driverDC == NULL) { - _tprintf(_T("Could not create device driver context!\n")); + _tprintf(_T("Could not create device driver wfi!\n")); return FALSE; } - context->changeBuffer = malloc(sizeof(GETCHANGESBUF)); - ZeroMemory(context->changeBuffer, sizeof(GETCHANGESBUF)); + wfi->changeBuffer = malloc(sizeof(GETCHANGESBUF)); + ZeroMemory(wfi->changeBuffer, sizeof(GETCHANGESBUF)); - status = ExtEscape(context->driverDC, dmf_esc_usm_pipe_map, 0, 0, sizeof(GETCHANGESBUF), (LPSTR) context->changeBuffer); + status = ExtEscape(wfi->driverDC, dmf_esc_usm_pipe_map, 0, 0, sizeof(GETCHANGESBUF), (LPSTR) wfi->changeBuffer); if (status <= 0) { _tprintf(_T("Failed to map shared memory from the driver! code %d\n"), status); } - b = (GETCHANGESBUF*) context->changeBuffer; + b = (GETCHANGESBUF*) wfi->changeBuffer; return TRUE; } /* Unmap the shared memory and release the DC */ -BOOL wf_mirror_driver_cleanup(wfInfo* context) +BOOL wf_mirror_driver_cleanup(wfInfo* wfi) { int status; - status = ExtEscape(context->driverDC, dmf_esc_usm_pipe_unmap, sizeof(GETCHANGESBUF), (LPSTR) context->changeBuffer, 0, 0); + status = ExtEscape(wfi->driverDC, dmf_esc_usm_pipe_unmap, sizeof(GETCHANGESBUF), (LPSTR) wfi->changeBuffer, 0, 0); if (status <= 0) { _tprintf(_T("Failed to unmap shared memory from the driver! code %d\n"), status); } - if (context->driverDC != NULL) + if (wfi->driverDC != NULL) { - status = DeleteDC(context->driverDC); + status = DeleteDC(wfi->driverDC); if (status == 0) { @@ -281,7 +288,7 @@ BOOL wf_mirror_driver_cleanup(wfInfo* context) } } - free(context->changeBuffer); + free(wfi->changeBuffer); return TRUE; } diff --git a/server/Windows/wf_mirage.h b/server/Windows/wf_mirage.h index 9287695d2..af52ab61c 100644 --- a/server/Windows/wf_mirage.h +++ b/server/Windows/wf_mirage.h @@ -200,11 +200,11 @@ typedef struct ULONG nColorBmPalEntries; } Esc_dmf_pointer_shape_get_OUT; -BOOL wf_mirror_driver_find_display_device(wfInfo* context); -BOOL wf_mirror_driver_display_device_attach(wfInfo* context, DWORD mode); -BOOL wf_mirror_driver_update(wfInfo* context, int unload); -BOOL wf_mirror_driver_map_memory(wfInfo* context); -BOOL wf_mirror_driver_cleanup(wfInfo* context); +BOOL wf_mirror_driver_find_display_device(wfInfo* wfi); +BOOL wf_mirror_driver_display_device_attach(wfInfo* wfi, DWORD mode); +BOOL wf_mirror_driver_update(wfInfo* wfi, int unload); +BOOL wf_mirror_driver_map_memory(wfInfo* wfi); +BOOL wf_mirror_driver_cleanup(wfInfo* wfi); void wf_mirror_driver_activate(wfInfo* wfi); void wf_mirror_driver_deactivate(wfInfo* wfi); diff --git a/server/Windows/wf_peer.c b/server/Windows/wf_peer.c index b0ae53490..89830bd00 100644 --- a/server/Windows/wf_peer.c +++ b/server/Windows/wf_peer.c @@ -74,7 +74,6 @@ void wf_peer_init(freerdp_peer* client) BOOL wf_peer_post_connect(freerdp_peer* client) { int i; - HDC hdc; wfInfo* wfi; rdpSettings* settings; wfPeerContext* context = (wfPeerContext*) client->context; @@ -82,30 +81,23 @@ BOOL wf_peer_post_connect(freerdp_peer* client) wfi = context->info; settings = client->settings; - /*hdc = GetDC(NULL); - wfi->width = GetDeviceCaps(hdc, HORZRES); - wfi->height = GetDeviceCaps(hdc, VERTRES); - wfi->bitsPerPixel = GetDeviceCaps(hdc, BITSPIXEL); - ReleaseDC(NULL, hdc); - */ - if ( - (get_screen_info(wfi->screenID, NULL, &wfi->width, &wfi->height, &wfi->bitsPerPixel) == 0) || - (wfi->width == 0) || - (wfi->height == 0) || + (get_screen_info(wfi->screenID, NULL, &wfi->servscreen_width, &wfi->servscreen_height, &wfi->bitsPerPixel) == 0) || + (wfi->servscreen_width == 0) || + (wfi->servscreen_height == 0) || (wfi->bitsPerPixel == 0) ) { _tprintf(_T("postconnect: error getting screen info for screen %d\n"), wfi->screenID); return FALSE; } - if ((settings->width != wfi->width) || (settings->height != wfi->height)) + if ((settings->width != wfi->servscreen_width) || (settings->height != wfi->servscreen_height)) { printf("Client requested resolution %dx%d, but will resize to %dx%d\n", - settings->width, settings->height, wfi->width, wfi->height); + settings->width, settings->height, wfi->servscreen_width, wfi->servscreen_height); - settings->width = wfi->width; - settings->height = wfi->height; + settings->width = wfi->servscreen_width; + settings->height = wfi->servscreen_height; settings->color_depth = wfi->bitsPerPixel; client->update->DesktopResize(client->update->context); diff --git a/server/Windows/wf_update.c b/server/Windows/wf_update.c index ad0b502a0..33fbeb76d 100644 --- a/server/Windows/wf_update.c +++ b/server/Windows/wf_update.c @@ -199,8 +199,8 @@ void wf_update_encoder_reset(wfInfo* wfi) { wfi->rfx_context = rfx_context_new(); wfi->rfx_context->mode = RLGR3; - wfi->rfx_context->width = wfi->width; - wfi->rfx_context->height = wfi->height; + wfi->rfx_context->width = wfi->servscreen_width; + wfi->rfx_context->height = wfi->servscreen_height; rfx_context_set_pixel_format(wfi->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8); wfi->s = stream_new(0xFFFF); } From b05bfbb6c144d42e4544f7171e7f5ee7de6f6ac9 Mon Sep 17 00:00:00 2001 From: Corey C Date: Wed, 31 Oct 2012 22:10:27 -0400 Subject: [PATCH 17/20] wfreerdp-server: fixed pointer offset on win8 multimon --- server/Windows/cli/wfreerdp.c | 11 ++++++++++- server/Windows/wf_dxgi.c | 14 +++++++------- server/Windows/wf_info.c | 24 ++++++++++++++++++++++++ server/Windows/wf_info.h | 1 + server/Windows/wf_input.c | 26 ++++++++++++++++++++++++-- 5 files changed, 66 insertions(+), 10 deletions(-) diff --git a/server/Windows/cli/wfreerdp.c b/server/Windows/cli/wfreerdp.c index 0b855becd..441ba516a 100644 --- a/server/Windows/cli/wfreerdp.c +++ b/server/Windows/cli/wfreerdp.c @@ -46,6 +46,8 @@ BOOL CALLBACK moncb(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARA IDcount++; + + return TRUE; } int main(int argc, char* argv[]) @@ -88,8 +90,15 @@ int main(int argc, char* argv[]) } { + int vscreen_w; + int vscreen_h; + vscreen_w = GetSystemMetrics(SM_CXVIRTUALSCREEN); + vscreen_h = GetSystemMetrics(SM_CYVIRTUALSCREEN); + printf("\n"); - EnumDisplayMonitors(NULL, NULL, moncb, NULL); + EnumDisplayMonitors(NULL, NULL, moncb, 0); + IDcount = 0; + printf("\nVirtual Screen = %dx%d\n", vscreen_w, vscreen_h); } return 0; diff --git a/server/Windows/wf_dxgi.c b/server/Windows/wf_dxgi.c index ac9b4b907..dd5ac3421 100644 --- a/server/Windows/wf_dxgi.c +++ b/server/Windows/wf_dxgi.c @@ -65,17 +65,17 @@ ID3D11Texture2D* sStage; DXGI_OUTDUPL_FRAME_INFO FrameInfo; -int wf_dxgi_init(wfInfo* context) +int wf_dxgi_init(wfInfo* wfi) { //not sure if needed gAcquiredDesktopImage = NULL; - if (wf_dxgi_createDevice(context) != 0) + if (wf_dxgi_createDevice(wfi) != 0) { return 1; } - if (wf_dxgi_getDuplication(context) != 0) + if (wf_dxgi_getDuplication(wfi) != 0) { return 1; } @@ -84,7 +84,7 @@ int wf_dxgi_init(wfInfo* context) } -int wf_dxgi_createDevice(wfInfo* context) +int wf_dxgi_createDevice(wfInfo* wfi) { HRESULT status; UINT DriverTypeIndex; @@ -108,7 +108,7 @@ int wf_dxgi_createDevice(wfInfo* context) return 0; } -int wf_dxgi_getDuplication(wfInfo* context) +int wf_dxgi_getDuplication(wfInfo* wfi) { HRESULT status; UINT dTop, i = 0; @@ -161,7 +161,7 @@ int wf_dxgi_getDuplication(wfInfo* context) ++i; } - dTop = context->screenID; + dTop = wfi->screenID; status = DxgiAdapter->lpVtbl->EnumOutputs(DxgiAdapter, dTop, &DxgiOutput); DxgiAdapter->lpVtbl->Release(DxgiAdapter); @@ -324,7 +324,7 @@ int wf_dxgi_nextFrame(wfInfo* wfi, UINT timeout) return 0; } -int wf_dxgi_getPixelData(wfInfo* context, BYTE** data, int* pitch, RECT* invalid) +int wf_dxgi_getPixelData(wfInfo* wfi, BYTE** data, int* pitch, RECT* invalid) { HRESULT status; D3D11_BOX Box; diff --git a/server/Windows/wf_info.c b/server/Windows/wf_info.c index e36a9f222..92543d7f6 100644 --- a/server/Windows/wf_info.c +++ b/server/Windows/wf_info.c @@ -32,6 +32,7 @@ #include "wf_dxgi.h" static wfInfo* wfInfoInstance = NULL; +static int _IDcount = 0; int wf_info_lock(wfInfo* wfi) { @@ -215,6 +216,10 @@ void wf_info_peer_register(wfInfo* wfi, wfPeerContext* context) context->info = wfi; context->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + //get the offset of the top left corner of selected screen + EnumDisplayMonitors(NULL, NULL, wf_info_monEnumCB, 0); + _IDcount = 0; + #ifdef WITH_WIN8 if (wfi->peerCount == 0) wf_dxgi_init(wfi); @@ -358,3 +363,22 @@ void wf_info_getScreenData(wfInfo* wfi, long* width, long* height, BYTE** pBits, } #endif } + +BOOL CALLBACK wf_info_monEnumCB(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) +{ + wfInfo * wfi; + + wfi = wf_info_get_instance(); + + if(_IDcount == wfi->screenID) + { + wfi->servscreen_xoffset = lprcMonitor->left; + wfi->servscreen_yoffset = lprcMonitor->top; + } + else + { + _IDcount++; + } + + return TRUE; +} diff --git a/server/Windows/wf_info.h b/server/Windows/wf_info.h index 3a2e8015c..8c1b6ae3f 100644 --- a/server/Windows/wf_info.h +++ b/server/Windows/wf_info.h @@ -40,5 +40,6 @@ void wf_info_clear_invalid_region(wfInfo* wfi); void wf_info_invalidate_full_screen(wfInfo* wfi); BOOL wf_info_have_invalid_region(wfInfo* wfi); void wf_info_getScreenData(wfInfo* wfi, long* width, long* height, BYTE** pBits, int* pitch); +BOOL CALLBACK wf_info_monEnumCB(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData); #endif /* WF_INFO_H */ \ No newline at end of file diff --git a/server/Windows/wf_input.c b/server/Windows/wf_input.c index 7124f2049..06b9f5350 100644 --- a/server/Windows/wf_input.c +++ b/server/Windows/wf_input.c @@ -24,6 +24,7 @@ #include #include "wf_input.h" +#include "wf_info.h" void wf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) { @@ -82,9 +83,17 @@ void wf_peer_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) } else { + wfInfo * wfi; + + wfi = wf_info_get_instance(); + + //width and height of primary screen (even in multimon setups width = (float) GetSystemMetrics(SM_CXSCREEN); height = (float) GetSystemMetrics(SM_CYSCREEN); + x += wfi->servscreen_xoffset; + y += wfi->servscreen_yoffset; + mouse_event.mi.dx = (LONG) ((float) x * (65535.0f / width)); mouse_event.mi.dy = (LONG) ((float) y * (65535.0f / height)); mouse_event.mi.dwFlags = MOUSEEVENTF_ABSOLUTE; @@ -138,8 +147,21 @@ void wf_peer_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT1 if (flags & PTR_FLAGS_MOVE) { - mouse_event.mi.dx = x * (0xFFFF / GetSystemMetrics(SM_CXSCREEN)); - mouse_event.mi.dy = y * (0xFFFF / GetSystemMetrics(SM_CYSCREEN)); + float width, height; + wfInfo * wfi; + + wfi = wf_info_get_instance(); + //width and height of primary screen (even in multimon setups + width = (float) GetSystemMetrics(SM_CXSCREEN); + height = (float) GetSystemMetrics(SM_CYSCREEN); + + x += wfi->servscreen_xoffset; + y += wfi->servscreen_yoffset; + + //mouse_event.mi.dx = x * (0xFFFF / width); + //mouse_event.mi.dy = y * (0xFFFF / height); + mouse_event.mi.dx = (LONG) ((float) x * (65535.0f / width)); + mouse_event.mi.dy = (LONG) ((float) y * (65535.0f / height)); mouse_event.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; SendInput(1, &mouse_event, sizeof(INPUT)); From 85c111834d3dd132697fc704e9b9c54ae4e41f28 Mon Sep 17 00:00:00 2001 From: Corey C Date: Wed, 31 Oct 2012 22:17:40 -0400 Subject: [PATCH 18/20] wfreerdp-server: fix default screen issue --- server/Windows/cli/wfreerdp.c | 2 ++ server/Windows/wf_info.c | 6 ++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/server/Windows/cli/wfreerdp.c b/server/Windows/cli/wfreerdp.c index 441ba516a..c7aba35fd 100644 --- a/server/Windows/cli/wfreerdp.c +++ b/server/Windows/cli/wfreerdp.c @@ -57,6 +57,8 @@ int main(int argc, char* argv[]) server = wfreerdp_server_new(); + set_screen_id(0); + //handle args index = 1; while (index < argc) diff --git a/server/Windows/wf_info.c b/server/Windows/wf_info.c index 92543d7f6..3bdadf1d4 100644 --- a/server/Windows/wf_info.c +++ b/server/Windows/wf_info.c @@ -375,10 +375,8 @@ BOOL CALLBACK wf_info_monEnumCB(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMo wfi->servscreen_xoffset = lprcMonitor->left; wfi->servscreen_yoffset = lprcMonitor->top; } - else - { - _IDcount++; - } + + _IDcount++; return TRUE; } From dd477a6a18815c8b29bebed591f24fa6b4215799 Mon Sep 17 00:00:00 2001 From: C-o-r-E Date: Thu, 1 Nov 2012 17:12:05 -0400 Subject: [PATCH 19/20] wfreerdp-server: multimon working on win7 --- server/Windows/wf_info.c | 2 +- server/Windows/wf_mirage.c | 18 ++++++++---------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/server/Windows/wf_info.c b/server/Windows/wf_info.c index 3bdadf1d4..3dc964011 100644 --- a/server/Windows/wf_info.c +++ b/server/Windows/wf_info.c @@ -359,7 +359,7 @@ void wf_info_getScreenData(wfInfo* wfi, long* width, long* height, BYTE** pBits, offset = (4 * wfi->invalid.left) + (wfi->invalid.top * wfi->servscreen_width * 4); *pBits = ((BYTE*) (changes->Userbuffer)) + offset; - *pitch = wfi->servscreen_width * 4; + *pitch = wfi->virtscreen_width * 4; } #endif } diff --git a/server/Windows/wf_mirage.c b/server/Windows/wf_mirage.c index 2b2b4a71e..df3409145 100644 --- a/server/Windows/wf_mirage.c +++ b/server/Windows/wf_mirage.c @@ -182,20 +182,18 @@ BOOL wf_mirror_driver_update(wfInfo* wfi, int unload) if (!unload) { - int vscreen_w; - int vscreen_h; //first let's get the virtual screen dimentions - vscreen_w = GetSystemMetrics(SM_CXVIRTUALSCREEN); - vscreen_h = GetSystemMetrics(SM_CYVIRTUALSCREEN); + wfi->virtscreen_width = GetSystemMetrics(SM_CXVIRTUALSCREEN); + wfi->virtscreen_height = GetSystemMetrics(SM_CYVIRTUALSCREEN); /* * Will have to come back to this for supporting non primary displays and multimonitor setups */ - dc = GetDC(NULL); + /*dc = GetDC(NULL); wfi->servscreen_width = GetDeviceCaps(dc, HORZRES); wfi->servscreen_height = GetDeviceCaps(dc, VERTRES); wfi->bitsPerPixel = GetDeviceCaps(dc, BITSPIXEL); - ReleaseDC(NULL, dc); + ReleaseDC(NULL, dc);*/ } else @@ -217,11 +215,11 @@ BOOL wf_mirror_driver_update(wfInfo* wfi, int unload) deviceMode->dmSize = sizeof(DEVMODE); deviceMode->dmDriverExtra = drvExtraSaved; - deviceMode->dmPelsWidth = wfi->servscreen_width; - deviceMode->dmPelsHeight = wfi->servscreen_height; + deviceMode->dmPelsWidth = wfi->virtscreen_width; + deviceMode->dmPelsHeight = wfi->virtscreen_height; deviceMode->dmBitsPerPel = wfi->bitsPerPixel; - deviceMode->dmPosition.x = 0; - deviceMode->dmPosition.y = 0; + deviceMode->dmPosition.x = wfi->servscreen_xoffset; + deviceMode->dmPosition.y = wfi->servscreen_yoffset; deviceMode->dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_POSITION; From c48cb01e36e127e036f60c59bf8c82b243431bb2 Mon Sep 17 00:00:00 2001 From: C-o-r-E Date: Thu, 1 Nov 2012 17:51:48 -0400 Subject: [PATCH 20/20] wfreerdp-server: fix default screen bug in multimon setup (win7) --- server/Windows/wf_info.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/server/Windows/wf_info.c b/server/Windows/wf_info.c index 3dc964011..5c0b3999a 100644 --- a/server/Windows/wf_info.c +++ b/server/Windows/wf_info.c @@ -308,7 +308,20 @@ void wf_info_find_invalid_region(wfInfo* wfi) for (i = wfi->lastUpdate; i != wfi->nextUpdate; i = (i + 1) % MAXCHANGES_BUF) { - UnionRect(&wfi->invalid, &wfi->invalid, &buf->buffer->pointrect[i].rect); + LPRECT lpR = &buf->buffer->pointrect[i].rect; + + //need to make sure we only get updates from the selected screen + if ( (lpR->left >= wfi->servscreen_xoffset) && + (lpR->right <= (wfi->servscreen_xoffset + wfi->servscreen_width) ) && + (lpR->top >= wfi->servscreen_yoffset) && + (lpR->bottom <= (wfi->servscreen_yoffset + wfi->servscreen_height) ) ) + { + UnionRect(&wfi->invalid, &wfi->invalid, lpR); + } + else + { + continue; + } } #endif @@ -323,6 +336,8 @@ void wf_info_find_invalid_region(wfInfo* wfi) if (wfi->invalid.bottom >= wfi->servscreen_height) wfi->invalid.bottom = wfi->servscreen_height - 1; + + //printf("invalid region: (%d, %d), (%d, %d)\n", wfi->invalid.left, wfi->invalid.top, wfi->invalid.right, wfi->invalid.bottom); } void wf_info_clear_invalid_region(wfInfo* wfi) @@ -357,7 +372,7 @@ void wf_info_getScreenData(wfInfo* wfi, long* width, long* height, BYTE** pBits, *width += 1; *height += 1; - offset = (4 * wfi->invalid.left) + (wfi->invalid.top * wfi->servscreen_width * 4); + offset = (4 * wfi->invalid.left) + (wfi->invalid.top * wfi->virtscreen_width * 4); *pBits = ((BYTE*) (changes->Userbuffer)) + offset; *pitch = wfi->virtscreen_width * 4; }