21 #include <winpr/tchar.h>
22 #include <winpr/windows.h>
24 #include "wf_mirage.h"
26 #include <freerdp/log.h>
27 #define TAG SERVER_TAG("Windows.mirror")
29 #define DEVICE_KEY_PREFIX _T("\\Registry\\Machine\\")
36 BOOL 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));
86 BOOL 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 privleges?");
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 privleges?");
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 privleges?");
140 void 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);
196 BOOL 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->dmPosition.x = wfi->servscreen_xoffset;
233 deviceMode->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);
248 BOOL 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);
290 BOOL 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);
315 BOOL 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;
351 void 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;