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(
nullptr, 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);
108 RegQueryValueEx(hKey, _T(
"Attach.ToDesktop"),
nullptr, &dwType, (BYTE*)&dwValue, &dwSize);
110 if (status != ERROR_SUCCESS)
112 WLog_DBG(TAG,
"Error querying RegKey: status=0x%08lX", status);
114 if (status == ERROR_ACCESS_DENIED)
115 WLog_DBG(TAG,
"access denied. Do you have admin privileges?");
123 dwSize =
sizeof(DWORD);
124 status = RegSetValueEx(hKey, _T(
"Attach.ToDesktop"), 0, REG_DWORD, (BYTE*)&dwValue, dwSize);
126 if (status != ERROR_SUCCESS)
128 WLog_DBG(TAG,
"Error writing registry key: %ld", status);
130 if (status == ERROR_ACCESS_DENIED)
131 WLog_DBG(TAG,
"access denied. Do you have admin privileges?");
141void wf_mirror_driver_print_display_change_status(LONG status)
143 TCHAR disp_change[64];
147 case DISP_CHANGE_SUCCESSFUL:
148 _tcscpy(disp_change, _T(
"DISP_CHANGE_SUCCESSFUL"));
151 case DISP_CHANGE_BADDUALVIEW:
152 _tcscpy(disp_change, _T(
"DISP_CHANGE_BADDUALVIEW"));
155 case DISP_CHANGE_BADFLAGS:
156 _tcscpy(disp_change, _T(
"DISP_CHANGE_BADFLAGS"));
159 case DISP_CHANGE_BADMODE:
160 _tcscpy(disp_change, _T(
"DISP_CHANGE_BADMODE"));
163 case DISP_CHANGE_BADPARAM:
164 _tcscpy(disp_change, _T(
"DISP_CHANGE_BADPARAM"));
167 case DISP_CHANGE_FAILED:
168 _tcscpy(disp_change, _T(
"DISP_CHANGE_FAILED"));
171 case DISP_CHANGE_NOTUPDATED:
172 _tcscpy(disp_change, _T(
"DISP_CHANGE_NOTUPDATED"));
175 case DISP_CHANGE_RESTART:
176 _tcscpy(disp_change, _T(
"DISP_CHANGE_RESTART"));
180 _tcscpy(disp_change, _T(
"DISP_CHANGE_UNKNOWN"));
184 if (status != DISP_CHANGE_SUCCESSFUL)
185 WLog_ERR(TAG,
"ChangeDisplaySettingsEx() failed with %s (%ld)", disp_change, status);
187 WLog_INFO(TAG,
"ChangeDisplaySettingsEx() succeeded with %s (%ld)", disp_change, status);
197BOOL wf_mirror_driver_update(wfInfo* wfi,
int mode)
203 LONG disp_change_status;
204 DWORD dmf_devmodewext_magic_sig = 0xDF20C0DE;
206 if ((mode != MIRROR_LOAD) && (mode != MIRROR_UNLOAD))
208 WLog_DBG(TAG,
"Invalid mirror mode!");
212 deviceMode = (DEVMODE*)malloc(
sizeof(DEVMODE) + EXT_DEVMODE_SIZE_MAX);
217 deviceMode->dmDriverExtra = 2 *
sizeof(DWORD);
218 extHdr = (DWORD*)((BYTE*)&deviceMode +
sizeof(DEVMODE));
219 extHdr[0] = dmf_devmodewext_magic_sig;
221 drvExtraSaved = deviceMode->dmDriverExtra;
222 memset(deviceMode, 0,
sizeof(DEVMODE) + EXT_DEVMODE_SIZE_MAX);
223 deviceMode->dmSize =
sizeof(DEVMODE);
224 deviceMode->dmDriverExtra = drvExtraSaved;
226 if (mode == MIRROR_LOAD)
228 wfi->virtscreen_width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
229 wfi->virtscreen_height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
230 deviceMode->dmPelsWidth = wfi->virtscreen_width;
231 deviceMode->dmPelsHeight = wfi->virtscreen_height;
232 deviceMode->dmBitsPerPel = wfi->bitsPerPixel;
233 deviceMode->u.s2.dmPosition.x = wfi->servscreen_xoffset;
234 deviceMode->u.s2.dmPosition.y = wfi->servscreen_yoffset;
237 deviceMode->dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_POSITION;
238 _tcsncpy_s(deviceMode->dmDeviceName, 32, wfi->deviceName, _tcslen(wfi->deviceName));
240 ChangeDisplaySettingsEx(wfi->deviceName, deviceMode,
nullptr, CDS_UPDATEREGISTRY,
nullptr);
241 status = (disp_change_status == DISP_CHANGE_SUCCESSFUL) ? TRUE : FALSE;
244 wf_mirror_driver_print_display_change_status(disp_change_status);
249BOOL wf_mirror_driver_map_memory(wfInfo* wfi)
252 wfi->driverDC = CreateDC(wfi->deviceName,
nullptr,
nullptr,
nullptr);
254 if (wfi->driverDC ==
nullptr)
256 WLog_ERR(TAG,
"Could not create device driver context!");
259 DWORD dw = GetLastError();
260 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
261 FORMAT_MESSAGE_IGNORE_INSERTS,
262 nullptr, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf,
265 WLog_ERR(TAG,
"CreateDC failed on device [%s] with error %lu: %s", wfi->deviceName, dw,
274 if (!wfi->changeBuffer)
277 status = ExtEscape(wfi->driverDC, dmf_esc_usm_pipe_map, 0, 0,
sizeof(
GETCHANGESBUF),
278 (LPSTR)wfi->changeBuffer);
282 WLog_ERR(TAG,
"Failed to map shared memory from the driver! code %d", status);
291BOOL wf_mirror_driver_cleanup(wfInfo* wfi)
294 status = ExtEscape(wfi->driverDC, dmf_esc_usm_pipe_unmap,
sizeof(
GETCHANGESBUF),
295 (LPSTR)wfi->changeBuffer, 0, 0);
299 WLog_ERR(TAG,
"Failed to unmap shared memory from the driver! code %d", status);
302 if (wfi->driverDC !=
nullptr)
304 status = DeleteDC(wfi->driverDC);
308 WLog_ERR(TAG,
"Failed to release DC!");
312 free(wfi->changeBuffer);
316BOOL wf_mirror_driver_activate(wfInfo* wfi)
318 if (!wfi->mirrorDriverActive)
320 WLog_DBG(TAG,
"Activating Mirror Driver");
322 if (wf_mirror_driver_find_display_device(wfi) == FALSE)
324 WLog_DBG(TAG,
"Could not find dfmirage mirror driver! Is it installed?");
328 if (wf_mirror_driver_display_device_attach(wfi, 1) == FALSE)
330 WLog_DBG(TAG,
"Could not attach display device!");
334 if (wf_mirror_driver_update(wfi, MIRROR_LOAD) == FALSE)
336 WLog_DBG(TAG,
"could not update system with new display settings!");
340 if (wf_mirror_driver_map_memory(wfi) == FALSE)
342 WLog_DBG(TAG,
"Unable to map memory for mirror driver!");
346 wfi->mirrorDriverActive = TRUE;
352void wf_mirror_driver_deactivate(wfInfo* wfi)
354 if (wfi->mirrorDriverActive)
356 WLog_DBG(TAG,
"Deactivating Mirror Driver");
357 wf_mirror_driver_cleanup(wfi);
358 wf_mirror_driver_display_device_attach(wfi, 0);
359 wf_mirror_driver_update(wfi, MIRROR_UNLOAD);
360 wfi->mirrorDriverActive = FALSE;