21#include <winpr/tchar.h> 
   22#include <winpr/windows.h> 
   26#include <freerdp/log.h> 
   27#define TAG SERVER_TAG("Windows.mirror") 
   29#define DEVICE_KEY_PREFIX _T("\\Registry\\Machine\\") 
   36BOOL wf_mirror_driver_find_display_device(wfInfo* wfi)
 
   41  DISPLAY_DEVICE deviceInfo;
 
   44  deviceInfo.cb = 
sizeof(deviceInfo);
 
   46  while (result = EnumDisplayDevices(NULL, deviceNumber, &deviceInfo, 0))
 
   48    if (_tcscmp(deviceInfo.DeviceString, _T(
"Mirage Driver")) == 0)
 
   51      int deviceKeyPrefixLength;
 
   52      deviceKeyPrefixLength = _tcslen(DEVICE_KEY_PREFIX);
 
   54      if (_tcsnicmp(deviceInfo.DeviceKey, DEVICE_KEY_PREFIX, deviceKeyPrefixLength) == 0)
 
   56        deviceKeyLength = _tcslen(deviceInfo.DeviceKey) - deviceKeyPrefixLength;
 
   57        wfi->deviceKey = (LPTSTR)malloc((deviceKeyLength + 1) * 
sizeof(TCHAR));
 
   62        _tcsncpy_s(wfi->deviceKey, deviceKeyLength + 1,
 
   63                   &deviceInfo.DeviceKey[deviceKeyPrefixLength], deviceKeyLength);
 
   66      _tcsncpy_s(wfi->deviceName, 32, deviceInfo.DeviceName, _tcslen(deviceInfo.DeviceName));
 
   86BOOL wf_mirror_driver_display_device_attach(wfInfo* wfi, DWORD mode)
 
   93  status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, wfi->deviceKey, 0, KEY_ALL_ACCESS | KEY_WOW64_64KEY,
 
   96  if (status != ERROR_SUCCESS)
 
   98    WLog_DBG(TAG, 
"Error opening RegKey: status=0x%08lX", status);
 
  100    if (status == ERROR_ACCESS_DENIED)
 
  101      WLog_DBG(TAG, 
"access denied. Do you have admin privileges?");
 
  106  dwSize = 
sizeof(DWORD);
 
  107  status = RegQueryValueEx(hKey, _T(
"Attach.ToDesktop"), NULL, &dwType, (BYTE*)&dwValue, &dwSize);
 
  109  if (status != ERROR_SUCCESS)
 
  111    WLog_DBG(TAG, 
"Error querying RegKey: status=0x%08lX", status);
 
  113    if (status == ERROR_ACCESS_DENIED)
 
  114      WLog_DBG(TAG, 
"access denied. Do you have admin privileges?");
 
  122    dwSize = 
sizeof(DWORD);
 
  123    status = RegSetValueEx(hKey, _T(
"Attach.ToDesktop"), 0, REG_DWORD, (BYTE*)&dwValue, dwSize);
 
  125    if (status != ERROR_SUCCESS)
 
  127      WLog_DBG(TAG, 
"Error writing registry key: %ld", status);
 
  129      if (status == ERROR_ACCESS_DENIED)
 
  130        WLog_DBG(TAG, 
"access denied. Do you have admin privileges?");
 
  140void wf_mirror_driver_print_display_change_status(LONG status)
 
  142  TCHAR disp_change[64];
 
  146    case DISP_CHANGE_SUCCESSFUL:
 
  147      _tcscpy(disp_change, _T(
"DISP_CHANGE_SUCCESSFUL"));
 
  150    case DISP_CHANGE_BADDUALVIEW:
 
  151      _tcscpy(disp_change, _T(
"DISP_CHANGE_BADDUALVIEW"));
 
  154    case DISP_CHANGE_BADFLAGS:
 
  155      _tcscpy(disp_change, _T(
"DISP_CHANGE_BADFLAGS"));
 
  158    case DISP_CHANGE_BADMODE:
 
  159      _tcscpy(disp_change, _T(
"DISP_CHANGE_BADMODE"));
 
  162    case DISP_CHANGE_BADPARAM:
 
  163      _tcscpy(disp_change, _T(
"DISP_CHANGE_BADPARAM"));
 
  166    case DISP_CHANGE_FAILED:
 
  167      _tcscpy(disp_change, _T(
"DISP_CHANGE_FAILED"));
 
  170    case DISP_CHANGE_NOTUPDATED:
 
  171      _tcscpy(disp_change, _T(
"DISP_CHANGE_NOTUPDATED"));
 
  174    case DISP_CHANGE_RESTART:
 
  175      _tcscpy(disp_change, _T(
"DISP_CHANGE_RESTART"));
 
  179      _tcscpy(disp_change, _T(
"DISP_CHANGE_UNKNOWN"));
 
  183  if (status != DISP_CHANGE_SUCCESSFUL)
 
  184    WLog_ERR(TAG, 
"ChangeDisplaySettingsEx() failed with %s (%ld)", disp_change, status);
 
  186    WLog_INFO(TAG, 
"ChangeDisplaySettingsEx() succeeded with %s (%ld)", disp_change, status);
 
  196BOOL wf_mirror_driver_update(wfInfo* wfi, 
int mode)
 
  202  LONG disp_change_status;
 
  203  DWORD dmf_devmodewext_magic_sig = 0xDF20C0DE;
 
  205  if ((mode != MIRROR_LOAD) && (mode != MIRROR_UNLOAD))
 
  207    WLog_DBG(TAG, 
"Invalid mirror mode!");
 
  211  deviceMode = (DEVMODE*)malloc(
sizeof(DEVMODE) + EXT_DEVMODE_SIZE_MAX);
 
  216  deviceMode->dmDriverExtra = 2 * 
sizeof(DWORD);
 
  217  extHdr = (DWORD*)((BYTE*)&deviceMode + 
sizeof(DEVMODE));
 
  218  extHdr[0] = dmf_devmodewext_magic_sig;
 
  220  drvExtraSaved = deviceMode->dmDriverExtra;
 
  221  memset(deviceMode, 0, 
sizeof(DEVMODE) + EXT_DEVMODE_SIZE_MAX);
 
  222  deviceMode->dmSize = 
sizeof(DEVMODE);
 
  223  deviceMode->dmDriverExtra = drvExtraSaved;
 
  225  if (mode == MIRROR_LOAD)
 
  227    wfi->virtscreen_width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
 
  228    wfi->virtscreen_height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
 
  229    deviceMode->dmPelsWidth = wfi->virtscreen_width;
 
  230    deviceMode->dmPelsHeight = wfi->virtscreen_height;
 
  231    deviceMode->dmBitsPerPel = wfi->bitsPerPixel;
 
  232    deviceMode->u.s2.dmPosition.x = wfi->servscreen_xoffset;
 
  233    deviceMode->u.s2.dmPosition.y = wfi->servscreen_yoffset;
 
  236  deviceMode->dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_POSITION;
 
  237  _tcsncpy_s(deviceMode->dmDeviceName, 32, wfi->deviceName, _tcslen(wfi->deviceName));
 
  239      ChangeDisplaySettingsEx(wfi->deviceName, deviceMode, NULL, CDS_UPDATEREGISTRY, NULL);
 
  240  status = (disp_change_status == DISP_CHANGE_SUCCESSFUL) ? TRUE : FALSE;
 
  243    wf_mirror_driver_print_display_change_status(disp_change_status);
 
  248BOOL wf_mirror_driver_map_memory(wfInfo* wfi)
 
  251  wfi->driverDC = CreateDC(wfi->deviceName, NULL, NULL, NULL);
 
  253  if (wfi->driverDC == NULL)
 
  255    WLog_ERR(TAG, 
"Could not create device driver context!");
 
  258      DWORD dw = GetLastError();
 
  259      FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
 
  260                        FORMAT_MESSAGE_IGNORE_INSERTS,
 
  261                    NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0,
 
  264      WLog_ERR(TAG, 
"CreateDC failed on device [%s] with error %lu: %s", wfi->deviceName, dw,
 
  273  if (!wfi->changeBuffer)
 
  276  status = ExtEscape(wfi->driverDC, dmf_esc_usm_pipe_map, 0, 0, 
sizeof(
GETCHANGESBUF),
 
  277                     (LPSTR)wfi->changeBuffer);
 
  281    WLog_ERR(TAG, 
"Failed to map shared memory from the driver! code %d", status);
 
  290BOOL wf_mirror_driver_cleanup(wfInfo* wfi)
 
  293  status = ExtEscape(wfi->driverDC, dmf_esc_usm_pipe_unmap, 
sizeof(
GETCHANGESBUF),
 
  294                     (LPSTR)wfi->changeBuffer, 0, 0);
 
  298    WLog_ERR(TAG, 
"Failed to unmap shared memory from the driver! code %d", status);
 
  301  if (wfi->driverDC != NULL)
 
  303    status = DeleteDC(wfi->driverDC);
 
  307      WLog_ERR(TAG, 
"Failed to release DC!");
 
  311  free(wfi->changeBuffer);
 
  315BOOL wf_mirror_driver_activate(wfInfo* wfi)
 
  317  if (!wfi->mirrorDriverActive)
 
  319    WLog_DBG(TAG, 
"Activating Mirror Driver");
 
  321    if (wf_mirror_driver_find_display_device(wfi) == FALSE)
 
  323      WLog_DBG(TAG, 
"Could not find dfmirage mirror driver! Is it installed?");
 
  327    if (wf_mirror_driver_display_device_attach(wfi, 1) == FALSE)
 
  329      WLog_DBG(TAG, 
"Could not attach display device!");
 
  333    if (wf_mirror_driver_update(wfi, MIRROR_LOAD) == FALSE)
 
  335      WLog_DBG(TAG, 
"could not update system with new display settings!");
 
  339    if (wf_mirror_driver_map_memory(wfi) == FALSE)
 
  341      WLog_DBG(TAG, 
"Unable to map memory for mirror driver!");
 
  345    wfi->mirrorDriverActive = TRUE;
 
  351void wf_mirror_driver_deactivate(wfInfo* wfi)
 
  353  if (wfi->mirrorDriverActive)
 
  355    WLog_DBG(TAG, 
"Deactivating Mirror Driver");
 
  356    wf_mirror_driver_cleanup(wfi);
 
  357    wf_mirror_driver_display_device_attach(wfi, 0);
 
  358    wf_mirror_driver_update(wfi, MIRROR_UNLOAD);
 
  359    wfi->mirrorDriverActive = FALSE;