diff --git a/include/freerdp/peer.h b/include/freerdp/peer.h index 470df19d7..da65c0019 100644 --- a/include/freerdp/peer.h +++ b/include/freerdp/peer.h @@ -72,6 +72,7 @@ struct rdp_freerdp_peer psPeerSendChannelData SendChannelData; psPeerReceiveChannelData ReceiveChannelData; + int pId; UINT32 ack_frame_id; BOOL local; BOOL connected; diff --git a/server/Windows/CMakeLists.txt b/server/Windows/CMakeLists.txt index 67c724a97..66b32951e 100644 --- a/server/Windows/CMakeLists.txt +++ b/server/Windows/CMakeLists.txt @@ -47,11 +47,14 @@ else() set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} cli/wfreerdp.c cli/wfreerdp.h) add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) endif() + if(WITH_WIN8) set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} d3d11 dxgi dxguid) endif() +set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} dsound) + set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-server) set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS diff --git a/server/Windows/wf_info.c b/server/Windows/wf_info.c index 15fa7edbb..5974f98d8 100644 --- a/server/Windows/wf_info.c +++ b/server/Windows/wf_info.c @@ -1,21 +1,21 @@ /** - * FreeRDP: A Remote Desktop Protocol Implementation - * FreeRDP Windows Server - * - * Copyright 2012 Corey Clayton - * - * 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. - */ +* FreeRDP: A Remote Desktop Protocol Client +* FreeRDP Windows Server +* +* Copyright 2012 Corey Clayton +* +* 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. +*/ #ifdef HAVE_CONFIG_H #include "config.h" @@ -41,19 +41,19 @@ int wf_info_lock(wfInfo* wfi) switch (dRes) { - case WAIT_ABANDONED: - case WAIT_OBJECT_0: - return TRUE; - break; + case WAIT_ABANDONED: + case WAIT_OBJECT_0: + return TRUE; + break; - case WAIT_TIMEOUT: - return FALSE; - break; + case WAIT_TIMEOUT: + return FALSE; + break; - case WAIT_FAILED: - printf("wf_info_lock failed with 0x%08X\n", GetLastError()); - return -1; - break; + case WAIT_FAILED: + printf("wf_info_lock failed with 0x%08X\n", GetLastError()); + return -1; + break; } return -1; @@ -67,19 +67,19 @@ int wf_info_try_lock(wfInfo* wfi, DWORD dwMilliseconds) switch (dRes) { - case WAIT_ABANDONED: - case WAIT_OBJECT_0: - return TRUE; - break; + case WAIT_ABANDONED: + case WAIT_OBJECT_0: + return TRUE; + break; - case WAIT_TIMEOUT: - return FALSE; - break; + case WAIT_TIMEOUT: + return FALSE; + break; - case WAIT_FAILED: - printf("wf_info_try_lock failed with 0x%08X\n", GetLastError()); - return -1; - break; + case WAIT_FAILED: + printf("wf_info_try_lock failed with 0x%08X\n", GetLastError()); + return -1; + break; } return -1; @@ -100,7 +100,7 @@ wfInfo* wf_info_init() { wfInfo* wfi; -/* + /* OSVERSIONINFOEX osvi; SYSTEM_INFO si; BOOL bOsVersionInfoEx; @@ -136,19 +136,32 @@ wfInfo* wf_info_init() _tprintf(_T("Failed to create update thread\n")); } - wfi->peers = (freerdp_peer**) malloc(sizeof(freerdp_peer*) * 32); + wfi->peers = (freerdp_peer**) malloc(sizeof(freerdp_peer*) * WF_INFO_MAXPEERS); + memset(wfi->peers, 0, sizeof(freerdp_peer*) * WF_INFO_MAXPEERS); - wfi->framesPerSecond = 24; + //Set FPS + wfi->framesPerSecond = WF_INFO_DEFAULT_FPS; status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey); - if (status == ERROR_SUCCESS) { if (RegQueryValueEx(hKey, _T("FramesPerSecond"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS) - wfi->framesPerSecond = dwValue; - + wfi->framesPerSecond = dwValue; } + RegCloseKey(hKey); + //Set input toggle + wfi->input_disabled = FALSE; + + status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey); + if (status == ERROR_SUCCESS) + { + if (RegQueryValueEx(hKey, _T("DisableInput"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS) + { + if (dwValue != 0) + wfi->input_disabled = TRUE; + } + } RegCloseKey(hKey); //detect windows version @@ -162,15 +175,15 @@ wfInfo* wf_info_init() wfi->win8 = FALSE; if(bOsVersionInfoEx != 0 ) { - if ( VER_PLATFORM_WIN32_NT==osvi.dwPlatformId && - osvi.dwMajorVersion > 4 ) - { - if ( osvi.dwMajorVersion == 6 && - osvi.dwMinorVersion == 2) - { - wfi->win8 = TRUE; - } - } + if ( VER_PLATFORM_WIN32_NT==osvi.dwPlatformId && + osvi.dwMajorVersion > 4 ) + { + if ( osvi.dwMajorVersion == 6 && + osvi.dwMinorVersion == 2) + { + wfi->win8 = TRUE; + } + } } */ } @@ -190,6 +203,15 @@ void wf_info_peer_register(wfInfo* wfi, wfPeerContext* context) { if (wf_info_lock(wfi) > 0) { + int i; + int peerId; + if (wfi->peerCount == WF_INFO_MAXPEERS) + { + context->socketClose = TRUE; + wf_info_unlock(wfi); + return; + } + context->info = wfi; context->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL); @@ -199,12 +221,25 @@ void wf_info_peer_register(wfInfo* wfi, wfPeerContext* context) #else wf_mirror_driver_activate(wfi); #endif + //look trhough the array of peers until an empty slot + for(i=0; ipeers[i] == NULL) + { + peerId = i; + break; + } + } - wfi->peers[wfi->peerCount++] = ((rdpContext*) context)->peer; - - printf("Registering Peer: %d\n", wfi->peerCount); + wfi->peers[peerId] = ((rdpContext*) context)->peer; + wfi->peers[peerId]->pId = peerId; + wfi->peerCount++; + printf("Registering Peer: id=%d #=%d\n", peerId, wfi->peerCount); wf_info_unlock(wfi); + + wfreerdp_server_peer_callback_event(peerId, WF_SRV_CALLBACK_EVENT_CONNECT); } } @@ -212,10 +247,14 @@ void wf_info_peer_unregister(wfInfo* wfi, wfPeerContext* context) { if (wf_info_lock(wfi) > 0) { - wfi->peers[--(wfi->peerCount)] = NULL; + int peerId; + + peerId = ((rdpContext*) context)->peer->pId; + wfi->peers[peerId] = NULL; + wfi->peerCount--; CloseHandle(context->updateEvent); - printf("Unregistering Peer: %d\n", wfi->peerCount); + printf("Unregistering Peer: id=%d, #=%d\n", peerId, wfi->peerCount); #ifdef WITH_WIN8 if (wfi->peerCount == 0) @@ -223,6 +262,8 @@ void wf_info_peer_unregister(wfInfo* wfi, wfPeerContext* context) #endif wf_info_unlock(wfi); + + wfreerdp_server_peer_callback_event(peerId, WF_SRV_CALLBACK_EVENT_DISCONNECT); } } diff --git a/server/Windows/wf_info.h b/server/Windows/wf_info.h index bad196d21..3a2e8015c 100644 --- a/server/Windows/wf_info.h +++ b/server/Windows/wf_info.h @@ -22,6 +22,9 @@ #include "wf_interface.h" +#define WF_INFO_DEFAULT_FPS 24 +#define WF_INFO_MAXPEERS 32 + int wf_info_lock(wfInfo* wfi); int wf_info_try_lock(wfInfo* wfi, DWORD dwMilliseconds); int wf_info_unlock(wfInfo* wfi); diff --git a/server/Windows/wf_input.c b/server/Windows/wf_input.c index 09fd9b077..7124f2049 100644 --- a/server/Windows/wf_input.c +++ b/server/Windows/wf_input.c @@ -164,3 +164,20 @@ void wf_peer_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT1 wf_peer_mouse_event(input, flags, x, y); } } + + +void wf_peer_keyboard_event_dummy(rdpInput* input, UINT16 flags, UINT16 code) +{ +} + +void wf_peer_unicode_keyboard_event_dummy(rdpInput* input, UINT16 flags, UINT16 code) +{ +} + +void wf_peer_mouse_event_dummy(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) +{ +} + +void wf_peer_extended_mouse_event_dummy(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) +{ +} diff --git a/server/Windows/wf_input.h b/server/Windows/wf_input.h index 8409cfdb0..d185f2bf9 100644 --- a/server/Windows/wf_input.h +++ b/server/Windows/wf_input.h @@ -27,4 +27,10 @@ void wf_peer_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code); void wf_peer_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y); void wf_peer_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y); +//dummy versions +void wf_peer_keyboard_event_dummy(rdpInput* input, UINT16 flags, UINT16 code); +void wf_peer_unicode_keyboard_event_dummy(rdpInput* input, UINT16 flags, UINT16 code); +void wf_peer_mouse_event_dummy(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y); +void wf_peer_extended_mouse_event_dummy(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y); + #endif /* WF_INPUT_H */ diff --git a/server/Windows/wf_interface.c b/server/Windows/wf_interface.c index 3a50a9dd8..fc5512a79 100644 --- a/server/Windows/wf_interface.c +++ b/server/Windows/wf_interface.c @@ -3,6 +3,7 @@ * FreeRDP Windows Server * * Copyright 2012 Marc-Andre Moreau + * Copyright 2012 Corey Clayton * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,15 +22,20 @@ #include "config.h" #endif + #include #include #include +#include #include "wf_peer.h" #include "wf_settings.h" +#include "wf_info.h" #include "wf_interface.h" +cbCallback cbEvent; + DWORD WINAPI wf_server_main_loop(LPVOID lpParam) { int i, fds; @@ -38,11 +44,15 @@ DWORD WINAPI wf_server_main_loop(LPVOID lpParam) void* rfds[32]; fd_set rfds_set; freerdp_listener* instance; + wfInfo* wfi; + + wfi = wf_info_get_instance(); + wfi->force_all_disconnect = FALSE; ZeroMemory(rfds, sizeof(rfds)); instance = (freerdp_listener*) lpParam; - while (1) + while(wfi->force_all_disconnect == FALSE) { rcount = 0; @@ -68,6 +78,7 @@ DWORD WINAPI wf_server_main_loop(LPVOID lpParam) if (max_fds == 0) break; + select(max_fds + 1, &rfds_set, NULL, NULL, NULL); if (instance->CheckFileDescriptor(instance) != TRUE) @@ -77,6 +88,8 @@ DWORD WINAPI wf_server_main_loop(LPVOID lpParam) } } + printf("wf_server_main_loop terminating\n"); + instance->Close(instance); return 0; @@ -103,6 +116,13 @@ BOOL wfreerdp_server_start(wfServer* server) BOOL wfreerdp_server_stop(wfServer* server) { + wfInfo* wfi; + + wfi = wf_info_get_instance(); + + printf("Stopping server\n"); + wfi->force_all_disconnect = TRUE; + server->instance->Close(server->instance); return TRUE; } @@ -120,6 +140,8 @@ wfServer* wfreerdp_server_new() server->port = 3389; } + cbEvent = NULL; + return server; } @@ -132,3 +154,141 @@ void wfreerdp_server_free(wfServer* server) freerdp_wsa_cleanup(); } + + +FREERDP_API BOOL wfreerdp_server_is_running(wfServer* server) +{ + DWORD tStatus; + BOOL bRet; + + bRet = GetExitCodeThread(server->thread, &tStatus); + if (bRet == 0) + { + printf("Error in call to GetExitCodeThread\n"); + return FALSE; + } + + if (tStatus == STILL_ACTIVE) + return TRUE; + return FALSE; +} + +FREERDP_API UINT32 wfreerdp_server_num_peers() +{ + wfInfo* wfi; + + wfi = wf_info_get_instance(); + return wfi->peerCount; +} + +FREERDP_API UINT32 wfreerdp_server_get_peer_hostname(int pId, wchar_t * dstStr) +{ + wfInfo* wfi; + freerdp_peer* peer; + + wfi = wf_info_get_instance(); + peer = wfi->peers[pId]; + + + if (peer) + { + UINT32 sLen; + + sLen = strnlen_s(peer->hostname, 50); + swprintf(dstStr, 50, L"%hs", peer->hostname); + return sLen; + } + else + { + printf("nonexistent peer id=%d\n", pId); + return 0; + } + +} + +FREERDP_API BOOL wfreerdp_server_peer_is_local(int pId) +{ + wfInfo* wfi; + freerdp_peer* peer; + + wfi = wf_info_get_instance(); + peer = wfi->peers[pId]; + + + if (peer) + { + return peer->local; + } + else + { + return FALSE; + } +} +FREERDP_API BOOL wfreerdp_server_peer_is_connected(int pId) +{ + wfInfo* wfi; + freerdp_peer* peer; + + wfi = wf_info_get_instance(); + peer = wfi->peers[pId]; + + + if (peer) + { + return peer->connected; + } + else + { + return FALSE; + } +} + +FREERDP_API BOOL wfreerdp_server_peer_is_activated(int pId) +{ + wfInfo* wfi; + freerdp_peer* peer; + + wfi = wf_info_get_instance(); + peer = wfi->peers[pId]; + + + if (peer) + { + return peer->activated; + } + else + { + return FALSE; + } +} + +FREERDP_API BOOL wfreerdp_server_peer_is_authenticated(int pId) +{ + wfInfo* wfi; + freerdp_peer* peer; + + wfi = wf_info_get_instance(); + peer = wfi->peers[pId]; + + + if (peer) + { + return peer->authenticated; + } + else + { + return FALSE; + } +} + +FREERDP_API void wfreerdp_server_register_callback_event(cbCallback cb) +{ + cbEvent = cb; +} + +void wfreerdp_server_peer_callback_event(int pId, UINT32 eType) +{ + if (cbEvent) + cbEvent(pId, eType); +} + diff --git a/server/Windows/wf_interface.h b/server/Windows/wf_interface.h index 16d4be6fb..e7400010c 100644 --- a/server/Windows/wf_interface.h +++ b/server/Windows/wf_interface.h @@ -1,21 +1,22 @@ /** - * FreeRDP: A Remote Desktop Protocol Implementation - * FreeRDP Windows Server - * - * Copyright 2012 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. - */ +* FreeRDP: A Remote Desktop Protocol Client +* FreeRDP Windows Server +* +* Copyright 2012 Marc-Andre Moreau +* Copyright 2012 Corey Clayton +* +* 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 WF_INTERFACE_H #define WF_INTERFACE_H @@ -30,6 +31,11 @@ #include #include +#define WF_SRV_CALLBACK_EVENT_CONNECT 1 +#define WF_SRV_CALLBACK_EVENT_DISCONNECT 2 +#define WF_SRV_CALLBACK_EVENT_ACTIVATE 4 +#define WF_SRV_CALLBACK_EVENT_AUTH 8 + typedef struct wf_info wfInfo; typedef struct wf_peer_context wfPeerContext; @@ -51,6 +57,9 @@ struct wf_info BOOL mirrorDriverActive; UINT framesWaiting; + HANDLE snd_mutex; + BOOL snd_stop; + RECT invalid; HANDLE mutex; BOOL updatePending; @@ -61,6 +70,9 @@ struct wf_info unsigned long lastUpdate; unsigned long nextUpdate; SURFACE_BITS_COMMAND cmd; + + BOOL input_disabled; + BOOL force_all_disconnect; }; struct wf_peer_context @@ -87,10 +99,25 @@ struct wf_server }; typedef struct wf_server wfServer; +typedef void (__stdcall* cbCallback) (int, UINT32); + FREERDP_API BOOL wfreerdp_server_start(wfServer* server); FREERDP_API BOOL wfreerdp_server_stop(wfServer* server); FREERDP_API wfServer* wfreerdp_server_new(); FREERDP_API void wfreerdp_server_free(wfServer* server); +FREERDP_API BOOL wfreerdp_server_is_running(wfServer* server); + +FREERDP_API UINT32 wfreerdp_server_num_peers(); +FREERDP_API UINT32 wfreerdp_server_get_peer_hostname(int pId, wchar_t * dstStr); +FREERDP_API BOOL wfreerdp_server_peer_is_local(int pId); +FREERDP_API BOOL wfreerdp_server_peer_is_connected(int pId); +FREERDP_API BOOL wfreerdp_server_peer_is_activated(int pId); +FREERDP_API BOOL wfreerdp_server_peer_is_authenticated(int pId); + +FREERDP_API void wfreerdp_server_register_callback_event(cbCallback cb); + +void wfreerdp_server_peer_callback_event(int pId, UINT32 eType); + #endif /* WF_INTERFACE_H */ diff --git a/server/Windows/wf_peer.c b/server/Windows/wf_peer.c index 54dcb6b7c..c0216114c 100644 --- a/server/Windows/wf_peer.c +++ b/server/Windows/wf_peer.c @@ -1,21 +1,22 @@ /** - * FreeRDP: A Remote Desktop Protocol Implementation - * FreeRDP Windows Server - * - * Copyright 2012 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. - */ +* FreeRDP: A Remote Desktop Protocol Client +* FreeRDP Windows Server +* +* Copyright 2012 Marc-Andre Moreau +* Copyright 2012 Corey Clayton +* +* 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. +*/ #ifdef HAVE_CONFIG_H #include "config.h" @@ -50,7 +51,13 @@ void wf_peer_context_free(freerdp_peer* client, wfPeerContext* context) wf_info_peer_unregister(context->info, context); if (context->rdpsnd) + { + printf("snd_free\n"); + wf_rdpsnd_lock(); + context->info->snd_stop = TRUE; rdpsnd_server_context_free(context->rdpsnd); + wf_rdpsnd_unlock(); + } WTSDestroyVirtualChannelManager(context->vcm); } @@ -60,7 +67,7 @@ void wf_peer_init(freerdp_peer* client) client->context_size = sizeof(wfPeerContext); client->ContextNew = (psPeerContextNew) wf_peer_context_new; client->ContextFree = (psPeerContextFree) wf_peer_context_free; - + freerdp_peer_context_new(client); } @@ -111,13 +118,15 @@ BOOL wf_peer_activate(freerdp_peer* client) { wfInfo* wfi; wfPeerContext* context = (wfPeerContext*) client->context; - + printf("PeerActivate\n"); wfi = context->info; client->activated = TRUE; wf_update_peer_activate(wfi, context); + wfreerdp_server_peer_callback_event(((rdpContext*) context)->peer->pId, WF_SRV_CALLBACK_EVENT_ACTIVATE); + return TRUE; } @@ -131,6 +140,8 @@ BOOL wf_peer_logon(freerdp_peer* client, SEC_WINNT_AUTH_IDENTITY* identity, BOOL identity->User, identity->Domain, identity->Password); } + + wfreerdp_server_peer_callback_event(((rdpContext*) client->context)->peer->pId, WF_SRV_CALLBACK_EVENT_AUTH); return TRUE; } @@ -181,10 +192,10 @@ DWORD WINAPI wf_peer_socket_listener(LPVOID lpParam) FD_SET(fds, &rfds_set); } - + if (max_fds == 0) break; - + select(max_fds + 1, &rfds_set, NULL, NULL, NULL); SetEvent(context->socketEvent); @@ -239,7 +250,20 @@ DWORD WINAPI wf_peer_main_loop(LPVOID lpParam) client->Initialize(client); context = (wfPeerContext*) client->context; + if (context->socketClose) + return 0; + wfi = context->info; + + if (wfi->input_disabled == TRUE) + { + printf("client input is disabled\n"); + client->input->KeyboardEvent = wf_peer_keyboard_event_dummy; + client->input->UnicodeKeyboardEvent = wf_peer_unicode_keyboard_event_dummy; + client->input->MouseEvent = wf_peer_mouse_event_dummy; + client->input->ExtendedMouseEvent = wf_peer_extended_mouse_event_dummy; + } + context->socketEvent = CreateEvent(NULL, TRUE, FALSE, NULL); printf("socketEvent created\n"); @@ -288,6 +312,13 @@ DWORD WINAPI wf_peer_main_loop(LPVOID lpParam) break; } + //force disconnect + if(wfi->force_all_disconnect == TRUE) + { + printf("Forcing Disconnect -> "); + break; + } + /* FIXME: we should wait on this, instead of calling it every time */ if (WTSVirtualChannelManagerCheckFileDescriptor(context->vcm) != TRUE) break; diff --git a/server/Windows/wf_rdpsnd.c b/server/Windows/wf_rdpsnd.c index 54ea83c64..8ef5b2775 100644 --- a/server/Windows/wf_rdpsnd.c +++ b/server/Windows/wf_rdpsnd.c @@ -24,9 +24,29 @@ #include #include +#include +#define CINTERFACE +#include +#include + #include #include "wf_rdpsnd.h" +#include "wf_info.h" + +/* + * Here are some temp things that shall be moved + * + */ +IDirectSoundCapture8 * cap; +IDirectSoundCaptureBuffer8* capBuf; +DSCBUFFERDESC dscbd; +DWORD capturePos; + +#define BYTESPERSEC 176400 + +//FIXME support multiple clients +wfPeerContext* latestPeer; static const rdpsndFormat test_audio_formats[] = { @@ -44,11 +64,107 @@ static const rdpsndFormat test_audio_formats[] = static void wf_peer_rdpsnd_activated(rdpsnd_server_context* context) { + HRESULT hr; + + LPDIRECTSOUNDCAPTUREBUFFER pDSCB; + WAVEFORMATEX wfx = {WAVE_FORMAT_PCM, 2, 44100, BYTESPERSEC, 4, 16, 0}; + + printf("RDPSND Activated\n"); + + hr = DirectSoundCaptureCreate8(NULL, &cap, NULL); + + if (FAILED(hr)) + { + _tprintf(_T("Failed to create sound capture device\n")); + return; + } + _tprintf(_T("Created sound capture device\n")); + + dscbd.dwSize = sizeof(DSCBUFFERDESC); + dscbd.dwFlags = 0; + dscbd.dwBufferBytes = BYTESPERSEC; + dscbd.dwReserved = 0; + dscbd.lpwfxFormat = &wfx; + dscbd.dwFXCount = 0; + dscbd.lpDSCFXDesc = NULL; + + hr = cap->lpVtbl->CreateCaptureBuffer(cap, &dscbd, &pDSCB, NULL); + + if (FAILED(hr)) + { + _tprintf(_T("Failed to create capture buffer\n")); + } + _tprintf(_T("Created capture buffer")); + + hr = pDSCB->lpVtbl->QueryInterface(pDSCB, &IID_IDirectSoundCaptureBuffer8, (LPVOID*)&capBuf); + if (FAILED(hr)) + { + _tprintf(_T("Failed to QI capture buffer\n")); + } + _tprintf(_T("Created IDirectSoundCaptureBuffer8\n")); + pDSCB->lpVtbl->Release(pDSCB); + + context->SelectFormat(context, 4); + context->SetVolume(context, 0x7FFF, 0x7FFF); + capturePos = 0; + + CreateThread(NULL, 0, wf_rdpsnd_thread, latestPeer, 0, NULL); + + +} + +int wf_rdpsnd_lock() +{ + DWORD dRes; + wfInfo* wfi; + + wfi = wf_info_get_instance(); + + dRes = WaitForSingleObject(wfi->snd_mutex, INFINITE); + + switch (dRes) + { + case WAIT_ABANDONED: + case WAIT_OBJECT_0: + return TRUE; + break; + + case WAIT_TIMEOUT: + return FALSE; + break; + + case WAIT_FAILED: + printf("wf_rdpsnd_lock failed with 0x%08X\n", GetLastError()); + return -1; + break; + } + + return -1; +} + +int wf_rdpsnd_unlock() +{ + wfInfo* wfi; + + wfi = wf_info_get_instance(); + + if (ReleaseMutex(wfi->snd_mutex) == 0) + { + printf("wf_rdpsnd_unlock failed with 0x%08X\n", GetLastError()); + return -1; + } + + return TRUE; } BOOL wf_peer_rdpsnd_init(wfPeerContext* context) { + wfInfo* wfi; + + wfi = wf_info_get_instance(); + + wfi->snd_mutex = CreateMutex(NULL, FALSE, NULL); context->rdpsnd = rdpsnd_server_context_new(context->vcm); context->rdpsnd->data = context; @@ -65,5 +181,121 @@ BOOL wf_peer_rdpsnd_init(wfPeerContext* context) context->rdpsnd->Initialize(context->rdpsnd); + latestPeer = context; + wfi->snd_stop = FALSE; return TRUE; } + +DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam) +{ + HRESULT hr; + DWORD beg, end; + DWORD diff, rate; + wfPeerContext* context; + wfInfo* wfi; + + wfi = wf_info_get_instance(); + + context = (wfPeerContext*)lpParam; + rate = 1000 / 5; + + _tprintf(_T("Trying to start capture\n")); + hr = capBuf->lpVtbl->Start(capBuf, DSCBSTART_LOOPING); + if (FAILED(hr)) + { + _tprintf(_T("Failed to start capture\n")); + } + _tprintf(_T("Capture started\n")); + + while (1) + { + VOID* pbCaptureData = NULL; + DWORD dwCaptureLength; + VOID* pbCaptureData2 = NULL; + DWORD dwCaptureLength2; + VOID* pbPlayData = NULL; + DWORD dwReadPos; + LONG lLockSize; + beg = GetTickCount(); + + if (wf_rdpsnd_lock() > 0) + { + //check for main exit condition + if (wfi->snd_stop == TRUE) + { + wf_rdpsnd_unlock(); + break; + } + + hr = capBuf->lpVtbl->GetCurrentPosition(capBuf, NULL, &dwReadPos); + if (FAILED(hr)) + { + _tprintf(_T("Failed to get read pos\n")); + wf_rdpsnd_unlock(); + break; + } + + lLockSize = dwReadPos - capturePos;//dscbd.dwBufferBytes; + if (lLockSize < 0) lLockSize += dscbd.dwBufferBytes; + + if (lLockSize == 0) + { + wf_rdpsnd_unlock(); + continue; + } + + + hr = capBuf->lpVtbl->Lock(capBuf, capturePos, lLockSize, &pbCaptureData, &dwCaptureLength, &pbCaptureData2, &dwCaptureLength2, 0L); + if (FAILED(hr)) + { + _tprintf(_T("Failed to lock sound capture buffer\n")); + wf_rdpsnd_unlock(); + break; + } + + //fwrite(pbCaptureData, 1, dwCaptureLength, pFile); + //fwrite(pbCaptureData2, 1, dwCaptureLength2, pFile); + + //FIXME: frames = bytes/(bytespersample * channels) + + context->rdpsnd->SendSamples(context->rdpsnd, pbCaptureData, dwCaptureLength/4); + context->rdpsnd->SendSamples(context->rdpsnd, pbCaptureData2, dwCaptureLength2/4); + + + hr = capBuf->lpVtbl->Unlock(capBuf, pbCaptureData, dwCaptureLength, pbCaptureData2, dwCaptureLength2); + if (FAILED(hr)) + { + _tprintf(_T("Failed to unlock sound capture buffer\n")); + wf_rdpsnd_unlock(); + return 0; + } + + //TODO keep track of location in buffer + capturePos += dwCaptureLength; + capturePos %= dscbd.dwBufferBytes; + capturePos += dwCaptureLength2; + capturePos %= dscbd.dwBufferBytes; + + wf_rdpsnd_unlock(); + } + + end = GetTickCount(); + diff = end - beg; + + if (diff < rate) + { + Sleep(rate - diff); + } + } + + _tprintf(_T("Trying to stop sound capture\n")); + hr = capBuf->lpVtbl->Stop(capBuf); + if (FAILED(hr)) + { + _tprintf(_T("Failed to stop capture\n")); + } + _tprintf(_T("Capture stopped\n")); + + + return 0; +} diff --git a/server/Windows/wf_rdpsnd.h b/server/Windows/wf_rdpsnd.h index 0289cd245..d54c4172d 100644 --- a/server/Windows/wf_rdpsnd.h +++ b/server/Windows/wf_rdpsnd.h @@ -26,7 +26,11 @@ #include "wf_interface.h" +int wf_rdpsnd_lock(); +int wf_rdpsnd_unlock(); BOOL wf_peer_rdpsnd_init(wfPeerContext* context); +DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam); + #endif /* WF_RDPSND_H */ diff --git a/server/Windows/wf_update.c b/server/Windows/wf_update.c index 95768fc12..ad0b502a0 100644 --- a/server/Windows/wf_update.c +++ b/server/Windows/wf_update.c @@ -1,21 +1,22 @@ /** - * FreeRDP: A Remote Desktop Protocol Implementation - * FreeRDP Windows Server - * - * Copyright 2012 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. - */ +* FreeRDP: A Remote Desktop Protocol Client +* FreeRDP Windows Server +* +* Copyright 2012 Marc-Andre Moreau +* Copyright 2012 Corey Clayton +* +* 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. +*/ #ifdef HAVE_CONFIG_H #include "config.h" @@ -37,6 +38,7 @@ DWORD WINAPI wf_update_thread(LPVOID lpParam) { int index; + int peerindex; DWORD fps; wfInfo* wfi; DWORD beg, end; @@ -62,14 +64,18 @@ DWORD WINAPI wf_update_thread(LPVOID lpParam) wf_update_encode(wfi); //printf("Start of parallel sending\n"); - - for (index = 0; index < wfi->peerCount; index++) + index = 0; + for (peerindex = 0; peerindex < wfi->peerCount; peerindex++) { - if (wfi->peers[index]->activated) + for (; index < WF_INFO_MAXPEERS; index++) { - //printf("Setting event for %d of %d\n", index + 1, wfi->activePeerCount); - SetEvent(((wfPeerContext*) wfi->peers[index]->context)->updateEvent); + if (wfi->peers[index] && wfi->peers[index]->activated) + { + //printf("Setting event for %d of %d\n", index + 1, wfi->activePeerCount); + SetEvent(((wfPeerContext*) wfi->peers[index]->context)->updateEvent); + } } + } for (index = 0; index < wfi->activePeerCount; index++) @@ -104,12 +110,12 @@ DWORD WINAPI wf_update_thread(LPVOID lpParam) void wf_update_encode(wfInfo* wfi) { - + RFX_RECT rect; long height, width; BYTE* pDataBits = NULL; int stride; - + SURFACE_BITS_COMMAND* cmd; wf_info_find_invalid_region(wfi); @@ -129,7 +135,7 @@ void wf_update_encode(wfInfo* wfi) stream_clear(wfi->s); rfx_compose_message(wfi->rfx_context, wfi->s, &rect, 1, - pDataBits, width, height, stride); + pDataBits, width, height, stride); wfi->frame_idx = wfi->rfx_context->frame_idx; @@ -156,10 +162,10 @@ void wf_update_peer_send(wfInfo* wfi, wfPeerContext* context) context->frame_idx = 0; /* - * When a new client connects, it is possible that old frames from - * from a previous encoding state remain. Those frames should be discarded - * as they will cause an error condition in mstsc. - */ + * When a new client connects, it is possible that old frames from + * from a previous encoding state remain. Those frames should be discarded + * as they will cause an error condition in mstsc. + */ if ((context->frame_idx + 1) != wfi->frame_idx) {