20 #include <freerdp/config.h>
24 #include <freerdp/build-config.h>
26 #include <winpr/tchar.h>
27 #include <winpr/windows.h>
30 #include "wf_update.h"
31 #include "wf_mirage.h"
34 #include <freerdp/log.h>
35 #define TAG SERVER_TAG("windows")
37 #define SERVER_KEY "Software\\" FREERDP_VENDOR_STRING "\\" FREERDP_PRODUCT_STRING "\\Server"
39 static wfInfo* wfInfoInstance = NULL;
40 static int _IDcount = 0;
42 BOOL wf_info_lock(wfInfo* wfi)
45 dRes = WaitForSingleObject(wfi->mutex, INFINITE);
57 WLog_ERR(TAG,
"wf_info_lock failed with 0x%08lX", GetLastError());
64 BOOL wf_info_try_lock(wfInfo* wfi, DWORD dwMilliseconds)
67 dRes = WaitForSingleObject(wfi->mutex, dwMilliseconds);
79 WLog_ERR(TAG,
"wf_info_try_lock failed with 0x%08lX", GetLastError());
86 BOOL wf_info_unlock(wfInfo* wfi)
88 if (!ReleaseMutex(wfi->mutex))
90 WLog_ERR(TAG,
"wf_info_unlock failed with 0x%08lX", GetLastError());
97 wfInfo* wf_info_init()
100 wfi = (wfInfo*)calloc(1,
sizeof(wfInfo));
109 wfi->mutex = CreateMutex(NULL, FALSE, NULL);
111 if (wfi->mutex == NULL)
113 WLog_ERR(TAG,
"CreateMutex error: %lu", GetLastError());
118 wfi->updateSemaphore = CreateSemaphore(NULL, 0, 32, NULL);
120 if (!wfi->updateSemaphore)
122 WLog_ERR(TAG,
"CreateSemaphore error: %lu", GetLastError());
123 (void)CloseHandle(wfi->mutex);
128 wfi->updateThread = CreateThread(NULL, 0, wf_update_thread, wfi, CREATE_SUSPENDED, NULL);
130 if (!wfi->updateThread)
132 WLog_ERR(TAG,
"Failed to create update thread");
133 (void)CloseHandle(wfi->mutex);
134 (void)CloseHandle(wfi->updateSemaphore);
140 (freerdp_peer**)calloc(FREERDP_SERVER_WIN_INFO_MAXPEERS,
sizeof(freerdp_peer*));
144 WLog_ERR(TAG,
"Failed to allocate memory for peer");
145 (void)CloseHandle(wfi->mutex);
146 (void)CloseHandle(wfi->updateSemaphore);
147 (void)CloseHandle(wfi->updateThread);
153 wfi->framesPerSecond = FREERDP_SERVER_WIN_INFO_DEFAULT_FPS;
155 RegOpenKeyExA(HKEY_LOCAL_MACHINE, SERVER_KEY, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
157 if (status == ERROR_SUCCESS)
159 if (RegQueryValueEx(hKey, _T(
"FramesPerSecond"), NULL, &dwType, (BYTE*)&dwValue,
160 &dwSize) == ERROR_SUCCESS)
161 wfi->framesPerSecond = dwValue;
166 wfi->input_disabled = FALSE;
168 RegOpenKeyExA(HKEY_LOCAL_MACHINE, SERVER_KEY, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
170 if (status == ERROR_SUCCESS)
172 if (RegQueryValueEx(hKey, _T(
"DisableInput"), NULL, &dwType, (BYTE*)&dwValue,
173 &dwSize) == ERROR_SUCCESS)
176 wfi->input_disabled = TRUE;
186 wfInfo* wf_info_get_instance()
188 if (wfInfoInstance == NULL)
189 wfInfoInstance = wf_info_init();
191 return wfInfoInstance;
194 BOOL wf_info_peer_register(wfInfo* wfi, wfPeerContext* context)
198 if (!wfi || !context)
201 if (!wf_info_lock(wfi))
204 if (wfi->peerCount == FREERDP_SERVER_WIN_INFO_MAXPEERS)
205 goto fail_peer_count;
209 if (!(context->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
210 goto fail_update_event;
213 EnumDisplayMonitors(NULL, NULL, wf_info_monEnumCB, 0);
217 if (wfi->peerCount == 0)
218 if (wf_dxgi_init(wfi) != 0)
219 goto fail_driver_init;
223 if (!wf_mirror_driver_activate(wfi))
224 goto fail_driver_init;
229 for (
int i = 0; i < FREERDP_SERVER_WIN_INFO_MAXPEERS; ++i)
232 if (wfi->peers[i] == NULL)
239 wfi->peers[peerId] = ((rdpContext*)context)->peer;
240 wfi->peers[peerId]->pId = peerId;
242 WLog_INFO(TAG,
"Registering Peer: id=%d #=%d", peerId, wfi->peerCount);
244 wfreerdp_server_peer_callback_event(peerId, FREERDP_SERVER_WIN_SRV_CALLBACK_EVENT_CONNECT);
247 (void)CloseHandle(context->updateEvent);
248 context->updateEvent = NULL;
251 context->socketClose = TRUE;
256 void wf_info_peer_unregister(wfInfo* wfi, wfPeerContext* context)
258 if (wf_info_lock(wfi))
261 peerId = ((rdpContext*)context)->peer->pId;
262 wfi->peers[peerId] = NULL;
264 (void)CloseHandle(context->updateEvent);
265 WLog_INFO(TAG,
"Unregistering Peer: id=%d, #=%d", peerId, wfi->peerCount);
268 if (wfi->peerCount == 0)
269 wf_dxgi_cleanup(wfi);
273 wfreerdp_server_peer_callback_event(peerId,
274 FREERDP_SERVER_WIN_SRV_CALLBACK_EVENT_DISCONNECT);
278 BOOL wf_info_have_updates(wfInfo* wfi)
282 if (wfi->framesWaiting == 0)
287 if (wfi->nextUpdate == wfi->lastUpdate)
294 void wf_info_update_changes(wfInfo* wfi)
297 wf_dxgi_nextFrame(wfi, wfi->framesPerSecond * 1000);
301 wfi->nextUpdate = buf->buffer->counter;
305 void wf_info_find_invalid_region(wfInfo* wfi)
308 wf_dxgi_getInvalidRegion(&wfi->invalid);
313 for (ULONG i = wfi->lastUpdate; i != wfi->nextUpdate; i = (i + 1) % MAXCHANGES_BUF)
315 LPRECT lpR = &buf->buffer->pointrect[i].rect;
318 if ((lpR->left >= wfi->servscreen_xoffset) &&
319 (lpR->right <= (wfi->servscreen_xoffset + wfi->servscreen_width)) &&
320 (lpR->top >= wfi->servscreen_yoffset) &&
321 (lpR->bottom <= (wfi->servscreen_yoffset + wfi->servscreen_height)))
323 UnionRect(&wfi->invalid, &wfi->invalid, lpR);
333 if (wfi->invalid.left < 0)
334 wfi->invalid.left = 0;
336 if (wfi->invalid.top < 0)
337 wfi->invalid.top = 0;
339 if (wfi->invalid.right >= wfi->servscreen_width)
340 wfi->invalid.right = wfi->servscreen_width - 1;
342 if (wfi->invalid.bottom >= wfi->servscreen_height)
343 wfi->invalid.bottom = wfi->servscreen_height - 1;
349 void wf_info_clear_invalid_region(wfInfo* wfi)
351 wfi->lastUpdate = wfi->nextUpdate;
352 SetRectEmpty(&wfi->invalid);
355 void wf_info_invalidate_full_screen(wfInfo* wfi)
357 SetRect(&wfi->invalid, 0, 0, wfi->servscreen_width, wfi->servscreen_height);
360 BOOL wf_info_have_invalid_region(wfInfo* wfi)
362 return IsRectEmpty(&wfi->invalid);
365 void wf_info_getScreenData(wfInfo* wfi,
long* width,
long* height, BYTE** pBits,
int* pitch)
367 *width = (wfi->invalid.right - wfi->invalid.left);
368 *height = (wfi->invalid.bottom - wfi->invalid.top);
370 wf_dxgi_getPixelData(wfi, pBits, pitch, &wfi->invalid);
378 offset = (4 * wfi->invalid.left) + (wfi->invalid.top * wfi->virtscreen_width * 4);
379 *pBits = ((BYTE*)(changes->Userbuffer)) + offset;
380 *pitch = wfi->virtscreen_width * 4;
385 BOOL CALLBACK wf_info_monEnumCB(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor,
389 wfi = wf_info_get_instance();
394 if (_IDcount == wfi->screenID)
396 wfi->servscreen_xoffset = lprcMonitor->left;
397 wfi->servscreen_yoffset = lprcMonitor->top;