20#include <freerdp/config.h> 
   24#include <freerdp/build-config.h> 
   26#include <winpr/tchar.h> 
   27#include <winpr/windows.h> 
   34#include <freerdp/log.h> 
   35#define TAG SERVER_TAG("windows") 
   37#define SERVER_KEY "Software\\" FREERDP_VENDOR_STRING "\\" FREERDP_PRODUCT_STRING "\\Server" 
   39static wfInfo* wfInfoInstance = NULL;
 
   40static int _IDcount = 0;
 
   42BOOL wf_info_lock(wfInfo* wfi)
 
   45  dRes = WaitForSingleObject(wfi->mutex, INFINITE);
 
   57      WLog_ERR(TAG, 
"wf_info_lock failed with 0x%08lX", GetLastError());
 
   64BOOL 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());
 
   86BOOL wf_info_unlock(wfInfo* wfi)
 
   88  if (!ReleaseMutex(wfi->mutex))
 
   90    WLog_ERR(TAG, 
"wf_info_unlock failed with 0x%08lX", GetLastError());
 
  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;
 
  186wfInfo* wf_info_get_instance()
 
  188  if (wfInfoInstance == NULL)
 
  189    wfInfoInstance = wf_info_init();
 
  191  return wfInfoInstance;
 
  194BOOL 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;
 
  256void 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);
 
  278BOOL wf_info_have_updates(wfInfo* wfi)
 
  282  if (wfi->framesWaiting == 0)
 
  287  if (wfi->nextUpdate == wfi->lastUpdate)
 
  294void wf_info_update_changes(wfInfo* wfi)
 
  297  wf_dxgi_nextFrame(wfi, wfi->framesPerSecond * 1000);
 
  301  wfi->nextUpdate = buf->buffer->counter;
 
  305void 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;
 
  349void wf_info_clear_invalid_region(wfInfo* wfi)
 
  351  wfi->lastUpdate = wfi->nextUpdate;
 
  352  SetRectEmpty(&wfi->invalid);
 
  355void wf_info_invalidate_full_screen(wfInfo* wfi)
 
  357  SetRect(&wfi->invalid, 0, 0, wfi->servscreen_width, wfi->servscreen_height);
 
  360BOOL wf_info_have_invalid_region(wfInfo* wfi)
 
  362  return IsRectEmpty(&wfi->invalid);
 
  365void 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;
 
  385BOOL 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;