From a732045c91d59d89e7fd8efb3be3f5ee67c22d39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 17 Jul 2014 18:27:40 -0400 Subject: [PATCH] wfreerdp-server: restore Win8 DXGI 1.2 support --- server/Windows/CMakeLists.txt | 2 +- server/Windows/wf_dxgi.c | 6 +- server/Windows/wf_info.c | 12 +- server/Windows/wf_input.c | 2 - server/Windows/wf_interface.h | 6 +- server/Windows/wf_peer.c | 8 - server/Windows/wf_update.c | 2 +- server/shadow/CMakeLists.txt | 14 +- server/shadow/Win/win_shadow.c | 287 +++++++++++++++++++++++++++++++++ server/shadow/Win/win_shadow.h | 49 ++++++ server/shadow/shadow_server.c | 8 + 11 files changed, 371 insertions(+), 25 deletions(-) create mode 100644 server/shadow/Win/win_shadow.c create mode 100644 server/shadow/Win/win_shadow.h diff --git a/server/Windows/CMakeLists.txt b/server/Windows/CMakeLists.txt index ae9ed7c92..3dc924651 100644 --- a/server/Windows/CMakeLists.txt +++ b/server/Windows/CMakeLists.txt @@ -70,7 +70,7 @@ else() endif() -if(WITH_WIN8) +if(CMAKE_WINDOWS_VERSION STREQUAL "WIN8") set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} d3d11 dxgi dxguid) endif() diff --git a/server/Windows/wf_dxgi.c b/server/Windows/wf_dxgi.c index dd5ac3421..43dd8af9e 100644 --- a/server/Windows/wf_dxgi.c +++ b/server/Windows/wf_dxgi.c @@ -23,7 +23,7 @@ #include "wf_interface.h" -#ifdef WITH_WIN8 +#ifdef WITH_DXGI_1_2 #define CINTERFACE @@ -67,9 +67,10 @@ DXGI_OUTDUPL_FRAME_INFO FrameInfo; int wf_dxgi_init(wfInfo* wfi) { - //not sure if needed gAcquiredDesktopImage = NULL; + printf("wf_dxgi_init\n"); + if (wf_dxgi_createDevice(wfi) != 0) { return 1; @@ -81,7 +82,6 @@ int wf_dxgi_init(wfInfo* wfi) } return 0; - } int wf_dxgi_createDevice(wfInfo* wfi) diff --git a/server/Windows/wf_info.c b/server/Windows/wf_info.c index c49d352df..7b972a9d2 100644 --- a/server/Windows/wf_info.c +++ b/server/Windows/wf_info.c @@ -188,7 +188,7 @@ void wf_info_peer_register(wfInfo* wfi, wfPeerContext* context) EnumDisplayMonitors(NULL, NULL, wf_info_monEnumCB, 0); _IDcount = 0; -#ifdef WITH_WIN8 +#ifdef WITH_DXGI_1_2 if (wfi->peerCount == 0) wf_dxgi_init(wfi); #else @@ -234,7 +234,7 @@ void wf_info_peer_unregister(wfInfo* wfi, wfPeerContext* context) printf("Unregistering Peer: id=%d, #=%d\n", peerId, wfi->peerCount); -#ifdef WITH_WIN8 +#ifdef WITH_DXGI_1_2 if (wfi->peerCount == 0) wf_dxgi_cleanup(wfi); #endif @@ -247,7 +247,7 @@ void wf_info_peer_unregister(wfInfo* wfi, wfPeerContext* context) BOOL wf_info_have_updates(wfInfo* wfi) { -#ifdef WITH_WIN8 +#ifdef WITH_DXGI_1_2 if(wfi->framesWaiting == 0) return FALSE; #else @@ -259,7 +259,7 @@ BOOL wf_info_have_updates(wfInfo* wfi) void wf_info_update_changes(wfInfo* wfi) { -#ifdef WITH_WIN8 +#ifdef WITH_DXGI_1_2 wf_dxgi_nextFrame(wfi, wfi->framesPerSecond * 1000); #else GETCHANGESBUF* buf; @@ -271,7 +271,7 @@ void wf_info_update_changes(wfInfo* wfi) void wf_info_find_invalid_region(wfInfo* wfi) { -#ifdef WITH_WIN8 +#ifdef WITH_DXGI_1_2 wf_dxgi_getInvalidRegion(&wfi->invalid); #else int i; @@ -334,7 +334,7 @@ void wf_info_getScreenData(wfInfo* wfi, long* width, long* height, BYTE** pBits, *width = (wfi->invalid.right - wfi->invalid.left); *height = (wfi->invalid.bottom - wfi->invalid.top); -#ifdef WITH_WIN8 +#ifdef WITH_DXGI_1_2 wf_dxgi_getPixelData(wfi, pBits, pitch, &wfi->invalid); #else { diff --git a/server/Windows/wf_input.c b/server/Windows/wf_input.c index 06b9f5350..7c70748fa 100644 --- a/server/Windows/wf_input.c +++ b/server/Windows/wf_input.c @@ -158,8 +158,6 @@ void wf_peer_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT1 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; diff --git a/server/Windows/wf_interface.h b/server/Windows/wf_interface.h index dc3af1c7f..6ab6b6f3e 100644 --- a/server/Windows/wf_interface.h +++ b/server/Windows/wf_interface.h @@ -32,6 +32,10 @@ #include +#if _WIN32_WINNT >= 0x0602 +#define WITH_DXGI_1_2 1 +#endif + #define WF_SRV_CALLBACK_EVENT_CONNECT 1 #define WF_SRV_CALLBACK_EVENT_DISCONNECT 2 #define WF_SRV_CALLBACK_EVENT_ACTIVATE 4 @@ -52,8 +56,6 @@ struct wf_info int servscreen_height; int servscreen_xoffset; int servscreen_yoffset; - //int width; - //int height; int frame_idx; int bitsPerPixel; diff --git a/server/Windows/wf_peer.c b/server/Windows/wf_peer.c index e214a007d..8d82391ba 100644 --- a/server/Windows/wf_peer.c +++ b/server/Windows/wf_peer.c @@ -127,14 +127,6 @@ BOOL wf_peer_activate(freerdp_peer* client) BOOL wf_peer_logon(freerdp_peer* client, SEC_WINNT_AUTH_IDENTITY* identity, BOOL automatic) { - /* - if (automatic) - { - _tprintf(_T("Logon: User:%s Domain:%s Password:%s\n"), - identity->User, identity->Domain, identity->Password); - } - */ - wfreerdp_server_peer_callback_event(((rdpContext*) client->context)->peer->pId, WF_SRV_CALLBACK_EVENT_AUTH); return TRUE; } diff --git a/server/Windows/wf_update.c b/server/Windows/wf_update.c index a8488557f..61d71181f 100644 --- a/server/Windows/wf_update.c +++ b/server/Windows/wf_update.c @@ -217,7 +217,7 @@ void wf_update_peer_activate(wfInfo* wfi, wfPeerContext* context) { if (wfi->activePeerCount < 1) { -#ifndef WITH_WIN8 +#ifndef WITH_DXGI_1_2 wf_mirror_driver_activate(wfi); #endif ResumeThread(wfi->updateThread); diff --git a/server/shadow/CMakeLists.txt b/server/shadow/CMakeLists.txt index aa737e35e..d37067216 100644 --- a/server/shadow/CMakeLists.txt +++ b/server/shadow/CMakeLists.txt @@ -135,6 +135,10 @@ set(${MODULE_PREFIX}_SRCS shadow_server.c shadow.h) +set(${MODULE_PREFIX}_WIN_SRCS + Win/win_shadow.c + Win/win_shadow.h) + set(${MODULE_PREFIX}_X11_SRCS X11/x11_shadow.c X11/x11_shadow.h) @@ -143,13 +147,19 @@ set(${MODULE_PREFIX}_MAC_SRCS Mac/mac_shadow.c Mac/mac_shadow.h) -if(X11_FOUND AND NOT APPLE) +if(WIN32) + set(WITH_SHADOW_WIN 1) +elseif(X11_FOUND AND NOT APPLE) set(WITH_SHADOW_X11 1) elseif(APPLE AND NOT IOS) set(WITH_SHADOW_MAC 1) endif() -if(WITH_SHADOW_X11) +if(WITH_SHADOW_WIN) + add_definitions(-DWITH_SHADOW_WIN) + list(APPEND ${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_WIN_SRCS}) + list(APPEND ${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_WIN_LIBS}) +elseif(WITH_SHADOW_X11) add_definitions(-DWITH_SHADOW_X11) list(APPEND ${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_X11_SRCS}) list(APPEND ${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_X11_LIBS}) diff --git a/server/shadow/Win/win_shadow.c b/server/shadow/Win/win_shadow.c new file mode 100644 index 000000000..2089bece9 --- /dev/null +++ b/server/shadow/Win/win_shadow.c @@ -0,0 +1,287 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * + * Copyright 2011-2014 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include +#include + +#include "../shadow_screen.h" +#include "../shadow_surface.h" + +#include "win_shadow.h" + +void win_shadow_input_synchronize_event(winShadowSubsystem* subsystem, UINT32 flags) +{ + +} + +void win_shadow_input_keyboard_event(winShadowSubsystem* subsystem, UINT16 flags, UINT16 code) +{ + INPUT event; + + event.type = INPUT_KEYBOARD; + event.ki.wVk = 0; + event.ki.wScan = code; + event.ki.dwFlags = KEYEVENTF_SCANCODE; + event.ki.dwExtraInfo = 0; + event.ki.time = 0; + + if (flags & KBD_FLAGS_RELEASE) + event.ki.dwFlags |= KEYEVENTF_KEYUP; + + if (flags & KBD_FLAGS_EXTENDED) + event.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY; + + SendInput(1, &event, sizeof(INPUT)); +} + +void win_shadow_input_unicode_keyboard_event(winShadowSubsystem* subsystem, UINT16 flags, UINT16 code) +{ + INPUT event; + + event.type = INPUT_KEYBOARD; + event.ki.wVk = 0; + event.ki.wScan = code; + event.ki.dwFlags = KEYEVENTF_UNICODE; + event.ki.dwExtraInfo = 0; + event.ki.time = 0; + + if (flags & KBD_FLAGS_RELEASE) + event.ki.dwFlags |= KEYEVENTF_KEYUP; + + SendInput(1, &event, sizeof(INPUT)); +} + +void win_shadow_input_mouse_event(winShadowSubsystem* subsystem, UINT16 flags, UINT16 x, UINT16 y) +{ + INPUT event; + float width; + float height; + + ZeroMemory(&event, sizeof(INPUT)); + + event.type = INPUT_MOUSE; + + if (flags & PTR_FLAGS_WHEEL) + { + event.mi.dwFlags = MOUSEEVENTF_WHEEL; + event.mi.mouseData = flags & WheelRotationMask; + + if (flags & PTR_FLAGS_WHEEL_NEGATIVE) + event.mi.mouseData *= -1; + + SendInput(1, &event, sizeof(INPUT)); + } + else + { + width = (float) GetSystemMetrics(SM_CXSCREEN); + height = (float) GetSystemMetrics(SM_CYSCREEN); + + event.mi.dx = (LONG) ((float) x * (65535.0f / width)); + event.mi.dy = (LONG) ((float) y * (65535.0f / height)); + event.mi.dwFlags = MOUSEEVENTF_ABSOLUTE; + + if (flags & PTR_FLAGS_MOVE) + { + event.mi.dwFlags |= MOUSEEVENTF_MOVE; + SendInput(1, &event, sizeof(INPUT)); + } + + event.mi.dwFlags = MOUSEEVENTF_ABSOLUTE; + + if (flags & PTR_FLAGS_BUTTON1) + { + if (flags & PTR_FLAGS_DOWN) + event.mi.dwFlags |= MOUSEEVENTF_LEFTDOWN; + else + event.mi.dwFlags |= MOUSEEVENTF_LEFTUP; + + SendInput(1, &event, sizeof(INPUT)); + } + else if (flags & PTR_FLAGS_BUTTON2) + { + if (flags & PTR_FLAGS_DOWN) + event.mi.dwFlags |= MOUSEEVENTF_RIGHTDOWN; + else + event.mi.dwFlags |= MOUSEEVENTF_RIGHTUP; + + SendInput(1, &event, sizeof(INPUT)); + } + else if (flags & PTR_FLAGS_BUTTON3) + { + if (flags & PTR_FLAGS_DOWN) + event.mi.dwFlags |= MOUSEEVENTF_MIDDLEDOWN; + else + event.mi.dwFlags |= MOUSEEVENTF_MIDDLEUP; + + SendInput(1, &event, sizeof(INPUT)); + } + } +} + +void win_shadow_input_extended_mouse_event(winShadowSubsystem* subsystem, UINT16 flags, UINT16 x, UINT16 y) +{ + INPUT event; + float width; + float height; + + ZeroMemory(&event, sizeof(INPUT)); + + if ((flags & PTR_XFLAGS_BUTTON1) || (flags & PTR_XFLAGS_BUTTON2)) + { + event.type = INPUT_MOUSE; + + if (flags & PTR_FLAGS_MOVE) + { + width = (float) GetSystemMetrics(SM_CXSCREEN); + height = (float) GetSystemMetrics(SM_CYSCREEN); + + event.mi.dx = (LONG)((float) x * (65535.0f / width)); + event.mi.dy = (LONG)((float) y * (65535.0f / height)); + event.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; + + SendInput(1, &event, sizeof(INPUT)); + } + + event.mi.dx = event.mi.dy = event.mi.dwFlags = 0; + + if (flags & PTR_XFLAGS_DOWN) + event.mi.dwFlags |= MOUSEEVENTF_XDOWN; + else + event.mi.dwFlags |= MOUSEEVENTF_XUP; + + if (flags & PTR_XFLAGS_BUTTON1) + event.mi.mouseData = XBUTTON1; + else if (flags & PTR_XFLAGS_BUTTON2) + event.mi.mouseData = XBUTTON2; + + SendInput(1, &event, sizeof(INPUT)); + } +} + +int win_shadow_surface_copy(winShadowSubsystem* subsystem) +{ + return 1; +} + +void* win_shadow_subsystem_thread(winShadowSubsystem* subsystem) +{ + DWORD status; + DWORD nCount; + HANDLE events[32]; + HANDLE StopEvent; + + StopEvent = subsystem->server->StopEvent; + + nCount = 0; + events[nCount++] = StopEvent; + + while (1) + { + status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); + + if (WaitForSingleObject(StopEvent, 0) == WAIT_OBJECT_0) + { + break; + } + } + + ExitThread(0); + return NULL; +} + +int win_shadow_subsystem_init(winShadowSubsystem* subsystem) +{ + return 1; +} + +int win_shadow_subsystem_uninit(winShadowSubsystem* subsystem) +{ + if (!subsystem) + return -1; + + return 1; +} + +int win_shadow_subsystem_start(winShadowSubsystem* subsystem) +{ + HANDLE thread; + + if (!subsystem) + return -1; + + thread = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE) win_shadow_subsystem_thread, + (void*) subsystem, 0, NULL); + + return 1; +} + +int win_shadow_subsystem_stop(winShadowSubsystem* subsystem) +{ + if (!subsystem) + return -1; + + return 1; +} + +void win_shadow_subsystem_free(winShadowSubsystem* subsystem) +{ + if (!subsystem) + return; + + win_shadow_subsystem_uninit(subsystem); + + free(subsystem); +} + +winShadowSubsystem* win_shadow_subsystem_new(rdpShadowServer* server) +{ + winShadowSubsystem* subsystem; + + subsystem = (winShadowSubsystem*) calloc(1, sizeof(winShadowSubsystem)); + + if (!subsystem) + return NULL; + + subsystem->server = server; + + subsystem->Init = (pfnShadowSubsystemInit) win_shadow_subsystem_init; + subsystem->Uninit = (pfnShadowSubsystemInit) win_shadow_subsystem_uninit; + subsystem->Start = (pfnShadowSubsystemStart) win_shadow_subsystem_start; + subsystem->Stop = (pfnShadowSubsystemStop) win_shadow_subsystem_stop; + subsystem->Free = (pfnShadowSubsystemFree) win_shadow_subsystem_free; + + subsystem->SurfaceCopy = (pfnShadowSurfaceCopy) win_shadow_surface_copy; + + subsystem->SynchronizeEvent = (pfnShadowSynchronizeEvent) win_shadow_input_synchronize_event; + subsystem->KeyboardEvent = (pfnShadowKeyboardEvent) win_shadow_input_keyboard_event; + subsystem->UnicodeKeyboardEvent = (pfnShadowUnicodeKeyboardEvent) win_shadow_input_unicode_keyboard_event; + subsystem->MouseEvent = (pfnShadowMouseEvent) win_shadow_input_mouse_event; + subsystem->ExtendedMouseEvent = (pfnShadowExtendedMouseEvent) win_shadow_input_extended_mouse_event; + + return subsystem; +} + +rdpShadowSubsystem* Win_ShadowCreateSubsystem(rdpShadowServer* server) +{ + return (rdpShadowSubsystem*) win_shadow_subsystem_new(server); +} diff --git a/server/shadow/Win/win_shadow.h b/server/shadow/Win/win_shadow.h new file mode 100644 index 000000000..1c27d4f86 --- /dev/null +++ b/server/shadow/Win/win_shadow.h @@ -0,0 +1,49 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * + * Copyright 2011-2014 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_SHADOW_SERVER_WIN_H +#define FREERDP_SHADOW_SERVER_WIN_H + +#include + +typedef struct win_shadow_subsystem winShadowSubsystem; + +#include +#include +#include +#include +#include + +struct win_shadow_subsystem +{ + RDP_SHADOW_SUBSYSTEM_COMMON(); + + +}; + +#ifdef __cplusplus +extern "C" { +#endif + + + +#ifdef __cplusplus +} +#endif + +#endif /* FREERDP_SHADOW_SERVER_WIN_H */ diff --git a/server/shadow/shadow_server.c b/server/shadow/shadow_server.c index 4601d4dd8..0cc757373 100644 --- a/server/shadow/shadow_server.c +++ b/server/shadow/shadow_server.c @@ -40,6 +40,10 @@ extern rdpShadowSubsystem* X11_ShadowCreateSubsystem(rdpShadowServer* server); extern rdpShadowSubsystem* Mac_ShadowCreateSubsystem(rdpShadowServer* server); #endif +#ifdef WITH_SHADOW_WIN +extern rdpShadowSubsystem* Win_ShadowCreateSubsystem(rdpShadowServer* server); +#endif + static COMMAND_LINE_ARGUMENT_A shadow_args[] = { { "port", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Server port" }, @@ -327,6 +331,10 @@ int shadow_server_init(rdpShadowServer* server) #ifdef WITH_SHADOW_MAC server->CreateSubsystem = Mac_ShadowCreateSubsystem; #endif + +#ifdef WITH_SHADOW_WIN + server->CreateSubsystem = Win_ShadowCreateSubsystem; +#endif if (server->CreateSubsystem) server->subsystem = server->CreateSubsystem(server);