diff --git a/server/Windows/cli/wfreerdp.c b/server/Windows/cli/wfreerdp.c index b40e796de..c7aba35fd 100644 --- a/server/Windows/cli/wfreerdp.c +++ b/server/Windows/cli/wfreerdp.c @@ -32,14 +32,100 @@ #include "wfreerdp.h" +int IDcount = 0; + +BOOL CALLBACK moncb(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) +{ + + printf("%d\t(%d, %d), (%d, %d)\n", + IDcount, + lprcMonitor->left, + lprcMonitor->top, + lprcMonitor->right, + lprcMonitor->bottom); + + + IDcount++; + + return TRUE; +} + int main(int argc, char* argv[]) { + int index; wfServer* server; server = wfreerdp_server_new(); - if (argc == 2) - server->port = (DWORD) atoi(argv[1]); + set_screen_id(0); + + //handle args + index = 1; + while (index < argc) + { + //first the args that will cause the program to terminate + if (strcmp("--list-screens", argv[index]) == 0) + { + _TCHAR name[128]; + int width; + int height; + int bpp; + int i; + + _tprintf(_T("Detecting screens...\n")); + _tprintf(_T("\nID\tResolution\t\tName (Interface)\n\n")); + + for (i=0; ; i++) + { + if (get_screen_info(i, name, &width, &height, &bpp) != 0) + { + if ( (width * height * bpp) == 0 ) + continue; + + _tprintf(_T("%d\t%dx%dx%d\t"), i, width, height, bpp); + _tprintf(_T("%s\n"), name); + } + else + { + break; + } + } + + { + int vscreen_w; + int vscreen_h; + vscreen_w = GetSystemMetrics(SM_CXVIRTUALSCREEN); + vscreen_h = GetSystemMetrics(SM_CYVIRTUALSCREEN); + + printf("\n"); + EnumDisplayMonitors(NULL, NULL, moncb, 0); + IDcount = 0; + printf("\nVirtual Screen = %dx%d\n", vscreen_w, vscreen_h); + } + + return 0; + } + + if (strcmp("--screen", argv[index]) == 0) + { + index++; + if (index == argc) + { + printf("missing screen id parameter\n"); + return 0; + } + + set_screen_id(atoi(argv[index])); + index++; + } + + + if (index == argc - 1) + { + server->port = (DWORD) atoi(argv[index]); + break; + } + } printf("Starting server\n"); diff --git a/server/Windows/wf_dxgi.c b/server/Windows/wf_dxgi.c index c50de40af..dd5ac3421 100644 --- a/server/Windows/wf_dxgi.c +++ b/server/Windows/wf_dxgi.c @@ -65,26 +65,38 @@ ID3D11Texture2D* sStage; DXGI_OUTDUPL_FRAME_INFO FrameInfo; -int wf_dxgi_init(wfInfo* context) +int wf_dxgi_init(wfInfo* wfi) +{ + //not sure if needed + gAcquiredDesktopImage = NULL; + + if (wf_dxgi_createDevice(wfi) != 0) + { + return 1; + } + + if (wf_dxgi_getDuplication(wfi) != 0) + { + return 1; + } + + return 0; + +} + +int wf_dxgi_createDevice(wfInfo* wfi) { HRESULT status; - UINT dTop, i = 0; - DXGI_OUTPUT_DESC desc; - IDXGIOutput * pOutput; UINT DriverTypeIndex; - IDXGIDevice* DxgiDevice = NULL; - IDXGIAdapter* DxgiAdapter = NULL; - IDXGIOutput* DxgiOutput = NULL; - IDXGIOutput1* DxgiOutput1 = NULL; - - gAcquiredDesktopImage = NULL; for (DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex) { - status = D3D11CreateDevice(NULL, DriverTypes[DriverTypeIndex], NULL, D3D11_CREATE_DEVICE_DEBUG, FeatureLevels, NumFeatureLevels, + status = D3D11CreateDevice(NULL, DriverTypes[DriverTypeIndex], NULL, 0, FeatureLevels, NumFeatureLevels, D3D11_SDK_VERSION, &gDevice, &FeatureLevel, &gContext); if (SUCCEEDED(status)) break; + + _tprintf(_T("D3D11CreateDevice returned [%d] for Driver Type %d\n"), status, DriverTypes[DriverTypeIndex]); } if (FAILED(status)) @@ -92,7 +104,21 @@ int wf_dxgi_init(wfInfo* context) _tprintf(_T("Failed to create device in InitializeDx\n")); return 1; } - + + return 0; +} + +int wf_dxgi_getDuplication(wfInfo* wfi) +{ + HRESULT status; + UINT dTop, i = 0; + DXGI_OUTPUT_DESC desc; + IDXGIOutput * pOutput; + IDXGIDevice* DxgiDevice = NULL; + IDXGIAdapter* DxgiAdapter = NULL; + IDXGIOutput* DxgiOutput = NULL; + IDXGIOutput1* DxgiOutput1 = NULL; + status = gDevice->lpVtbl->QueryInterface(gDevice, &IID_IDXGIDevice, (void**) &DxgiDevice); if (FAILED(status)) @@ -135,7 +161,7 @@ int wf_dxgi_init(wfInfo* context) ++i; } - dTop = 0; + dTop = wfi->screenID; status = DxgiAdapter->lpVtbl->EnumOutputs(DxgiAdapter, dTop, &DxgiOutput); DxgiAdapter->lpVtbl->Release(DxgiAdapter); @@ -169,13 +195,14 @@ int wf_dxgi_init(wfInfo* context) return 1; } - _tprintf(_T("Failed to get duplicate output\n")); + _tprintf(_T("Failed to get duplicate output. Status = %#X\n"), status); return 1; } return 0; } + int wf_dxgi_cleanup(wfInfo* wfi) { if (wfi->framesWaiting > 0) @@ -212,7 +239,7 @@ int wf_dxgi_cleanup(wfInfo* wfi) int wf_dxgi_nextFrame(wfInfo* wfi, UINT timeout) { - HRESULT status; + HRESULT status = 0; UINT i = 0; UINT DataBufferSize = 0; BYTE* DataBuffer = NULL; @@ -238,16 +265,39 @@ int wf_dxgi_nextFrame(wfInfo* wfi, UINT timeout) if (FAILED(status)) { - //_tprintf(_T("Failed to acquire next frame\n")); - - status = gOutputDuplication->lpVtbl->ReleaseFrame(gOutputDuplication); - - if (FAILED(status)) + if (status == DXGI_ERROR_ACCESS_LOST) { - //_tprintf(_T("Failed to release frame\n")); + _tprintf(_T("Failed to acquire next frame with status=%#X\n"), status); + _tprintf(_T("Trying to reinitialize due to ACCESS LOST...")); + if (gAcquiredDesktopImage) + { + gAcquiredDesktopImage->lpVtbl->Release(gAcquiredDesktopImage); + gAcquiredDesktopImage = NULL; + } + + if (gOutputDuplication) + { + gOutputDuplication->lpVtbl->Release(gOutputDuplication); + gOutputDuplication = NULL; + } + + wf_dxgi_getDuplication(wfi); + + return 1; } + else + { + _tprintf(_T("Failed to acquire next frame with status=%#X\n"), status); + + status = gOutputDuplication->lpVtbl->ReleaseFrame(gOutputDuplication); + + if (FAILED(status)) + { + _tprintf(_T("Failed to release frame with status=%d\n"), status); + } - return 1; + return 1; + } } status = DesktopResource->lpVtbl->QueryInterface(DesktopResource, &IID_ID3D11Texture2D, (void**) &gAcquiredDesktopImage); @@ -261,10 +311,20 @@ int wf_dxgi_nextFrame(wfInfo* wfi, UINT timeout) wfi->framesWaiting = FrameInfo.AccumulatedFrames; + if (FrameInfo.AccumulatedFrames == 0) + { + status = gOutputDuplication->lpVtbl->ReleaseFrame(gOutputDuplication); + + if (FAILED(status)) + { + _tprintf(_T("Failed to release frame with status=%d\n"), status); + } + } + return 0; } -int wf_dxgi_getPixelData(wfInfo* context, BYTE** data, int* pitch, RECT* invalid) +int wf_dxgi_getPixelData(wfInfo* wfi, BYTE** data, int* pitch, RECT* invalid) { HRESULT status; D3D11_BOX Box; diff --git a/server/Windows/wf_dxgi.h b/server/Windows/wf_dxgi.h index c7b73b803..1f47ee3a8 100644 --- a/server/Windows/wf_dxgi.h +++ b/server/Windows/wf_dxgi.h @@ -24,6 +24,10 @@ int wf_dxgi_init(wfInfo* context); +int wf_dxgi_createDevice(wfInfo* context); + +int wf_dxgi_getDuplication(wfInfo* context); + int wf_dxgi_cleanup(wfInfo* context); int wf_dxgi_nextFrame(wfInfo* context, UINT timeout); diff --git a/server/Windows/wf_info.c b/server/Windows/wf_info.c index 5974f98d8..5c0b3999a 100644 --- a/server/Windows/wf_info.c +++ b/server/Windows/wf_info.c @@ -32,6 +32,7 @@ #include "wf_dxgi.h" static wfInfo* wfInfoInstance = NULL; +static int _IDcount = 0; int wf_info_lock(wfInfo* wfi) { @@ -215,6 +216,10 @@ void wf_info_peer_register(wfInfo* wfi, wfPeerContext* context) context->info = wfi; context->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + //get the offset of the top left corner of selected screen + EnumDisplayMonitors(NULL, NULL, wf_info_monEnumCB, 0); + _IDcount = 0; + #ifdef WITH_WIN8 if (wfi->peerCount == 0) wf_dxgi_init(wfi); @@ -282,7 +287,7 @@ BOOL wf_info_have_updates(wfInfo* wfi) void wf_info_update_changes(wfInfo* wfi) { #ifdef WITH_WIN8 - wf_dxgi_nextFrame(wfi, wfi->framesPerSecond / 1000); + wf_dxgi_nextFrame(wfi, wfi->framesPerSecond * 1000); #else GETCHANGESBUF* buf; @@ -303,7 +308,20 @@ void wf_info_find_invalid_region(wfInfo* wfi) for (i = wfi->lastUpdate; i != wfi->nextUpdate; i = (i + 1) % MAXCHANGES_BUF) { - UnionRect(&wfi->invalid, &wfi->invalid, &buf->buffer->pointrect[i].rect); + LPRECT lpR = &buf->buffer->pointrect[i].rect; + + //need to make sure we only get updates from the selected screen + if ( (lpR->left >= wfi->servscreen_xoffset) && + (lpR->right <= (wfi->servscreen_xoffset + wfi->servscreen_width) ) && + (lpR->top >= wfi->servscreen_yoffset) && + (lpR->bottom <= (wfi->servscreen_yoffset + wfi->servscreen_height) ) ) + { + UnionRect(&wfi->invalid, &wfi->invalid, lpR); + } + else + { + continue; + } } #endif @@ -313,11 +331,13 @@ void wf_info_find_invalid_region(wfInfo* wfi) if (wfi->invalid.top < 0) wfi->invalid.top = 0; - if (wfi->invalid.right >= wfi->width) - wfi->invalid.right = wfi->width - 1; + if (wfi->invalid.right >= wfi->servscreen_width) + wfi->invalid.right = wfi->servscreen_width - 1; - if (wfi->invalid.bottom >= wfi->height) - wfi->invalid.bottom = wfi->height - 1; + if (wfi->invalid.bottom >= wfi->servscreen_height) + wfi->invalid.bottom = wfi->servscreen_height - 1; + + //printf("invalid region: (%d, %d), (%d, %d)\n", wfi->invalid.left, wfi->invalid.top, wfi->invalid.right, wfi->invalid.bottom); } void wf_info_clear_invalid_region(wfInfo* wfi) @@ -328,7 +348,7 @@ void wf_info_clear_invalid_region(wfInfo* wfi) void wf_info_invalidate_full_screen(wfInfo* wfi) { - SetRect(&wfi->invalid, 0, 0, wfi->width, wfi->height); + SetRect(&wfi->invalid, 0, 0, wfi->servscreen_width, wfi->servscreen_height); } BOOL wf_info_have_invalid_region(wfInfo* wfi) @@ -352,9 +372,26 @@ void wf_info_getScreenData(wfInfo* wfi, long* width, long* height, BYTE** pBits, *width += 1; *height += 1; - offset = (4 * wfi->invalid.left) + (wfi->invalid.top * wfi->width * 4); + offset = (4 * wfi->invalid.left) + (wfi->invalid.top * wfi->virtscreen_width * 4); *pBits = ((BYTE*) (changes->Userbuffer)) + offset; - *pitch = wfi->width * 4; + *pitch = wfi->virtscreen_width * 4; } #endif } + +BOOL CALLBACK wf_info_monEnumCB(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) +{ + wfInfo * wfi; + + wfi = wf_info_get_instance(); + + if(_IDcount == wfi->screenID) + { + wfi->servscreen_xoffset = lprcMonitor->left; + wfi->servscreen_yoffset = lprcMonitor->top; + } + + _IDcount++; + + return TRUE; +} diff --git a/server/Windows/wf_info.h b/server/Windows/wf_info.h index 3a2e8015c..8c1b6ae3f 100644 --- a/server/Windows/wf_info.h +++ b/server/Windows/wf_info.h @@ -40,5 +40,6 @@ void wf_info_clear_invalid_region(wfInfo* wfi); void wf_info_invalidate_full_screen(wfInfo* wfi); BOOL wf_info_have_invalid_region(wfInfo* wfi); void wf_info_getScreenData(wfInfo* wfi, long* width, long* height, BYTE** pBits, int* pitch); +BOOL CALLBACK wf_info_monEnumCB(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData); #endif /* WF_INFO_H */ \ No newline at end of file diff --git a/server/Windows/wf_input.c b/server/Windows/wf_input.c index 7124f2049..06b9f5350 100644 --- a/server/Windows/wf_input.c +++ b/server/Windows/wf_input.c @@ -24,6 +24,7 @@ #include #include "wf_input.h" +#include "wf_info.h" void wf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code) { @@ -82,9 +83,17 @@ void wf_peer_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) } else { + wfInfo * wfi; + + wfi = wf_info_get_instance(); + + //width and height of primary screen (even in multimon setups width = (float) GetSystemMetrics(SM_CXSCREEN); height = (float) GetSystemMetrics(SM_CYSCREEN); + x += wfi->servscreen_xoffset; + y += wfi->servscreen_yoffset; + mouse_event.mi.dx = (LONG) ((float) x * (65535.0f / width)); mouse_event.mi.dy = (LONG) ((float) y * (65535.0f / height)); mouse_event.mi.dwFlags = MOUSEEVENTF_ABSOLUTE; @@ -138,8 +147,21 @@ void wf_peer_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT1 if (flags & PTR_FLAGS_MOVE) { - mouse_event.mi.dx = x * (0xFFFF / GetSystemMetrics(SM_CXSCREEN)); - mouse_event.mi.dy = y * (0xFFFF / GetSystemMetrics(SM_CYSCREEN)); + float width, height; + wfInfo * wfi; + + wfi = wf_info_get_instance(); + //width and height of primary screen (even in multimon setups + width = (float) GetSystemMetrics(SM_CXSCREEN); + height = (float) GetSystemMetrics(SM_CYSCREEN); + + x += wfi->servscreen_xoffset; + y += wfi->servscreen_yoffset; + + //mouse_event.mi.dx = x * (0xFFFF / width); + //mouse_event.mi.dy = y * (0xFFFF / height); + mouse_event.mi.dx = (LONG) ((float) x * (65535.0f / width)); + mouse_event.mi.dy = (LONG) ((float) y * (65535.0f / height)); mouse_event.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; SendInput(1, &mouse_event, sizeof(INPUT)); diff --git a/server/Windows/wf_interface.c b/server/Windows/wf_interface.c index fc5512a79..79030f18a 100644 --- a/server/Windows/wf_interface.c +++ b/server/Windows/wf_interface.c @@ -36,6 +36,45 @@ cbCallback cbEvent; +int get_screen_info(int id, _TCHAR* name, int* width, int* height, int* bpp) +{ + DISPLAY_DEVICE dd; + + memset(&dd, 0, sizeof(DISPLAY_DEVICE)); + dd.cb = sizeof(DISPLAY_DEVICE); + + if (EnumDisplayDevices(NULL, id, &dd, 0) != 0) + { + HDC dc; + + if (name != NULL) + _stprintf(name, _T("%s (%s)"), dd.DeviceName, dd.DeviceString); + + dc = CreateDC(NULL, dd.DeviceName, NULL, NULL); + *width = GetDeviceCaps(dc, HORZRES); + *height = GetDeviceCaps(dc, VERTRES); + *bpp = GetDeviceCaps(dc, BITSPIXEL); + ReleaseDC(NULL, dc); + + } + else + { + return 0; + } + + return 1; +} + +void set_screen_id(int id) +{ + wfInfo* wfi; + + wfi = wf_info_get_instance(); + wfi->screenID = id; + + return; +} + DWORD WINAPI wf_server_main_loop(LPVOID lpParam) { int i, fds; diff --git a/server/Windows/wf_interface.h b/server/Windows/wf_interface.h index e7400010c..83819eac0 100644 --- a/server/Windows/wf_interface.h +++ b/server/Windows/wf_interface.h @@ -29,6 +29,7 @@ #include #include + #include #define WF_SRV_CALLBACK_EVENT_CONNECT 1 @@ -42,8 +43,18 @@ typedef struct wf_peer_context wfPeerContext; struct wf_info { STREAM* s; - int width; - int height; + + //screen and monitor info + int screenID; + int virtscreen_width; + int virtscreen_height; + int servscreen_width; + int servscreen_height; + int servscreen_xoffset; + int servscreen_yoffset; + //int width; + //int height; + int frame_idx; int bitsPerPixel; HDC driverDC; @@ -101,6 +112,9 @@ typedef struct wf_server wfServer; typedef void (__stdcall* cbCallback) (int, UINT32); +FREERDP_API int get_screen_info(int id, _TCHAR* name, int* w, int* h, int* b); +FREERDP_API void set_screen_id(int id); + FREERDP_API BOOL wfreerdp_server_start(wfServer* server); FREERDP_API BOOL wfreerdp_server_stop(wfServer* server); diff --git a/server/Windows/wf_mirage.c b/server/Windows/wf_mirage.c index 150a5caae..df3409145 100644 --- a/server/Windows/wf_mirage.c +++ b/server/Windows/wf_mirage.c @@ -26,10 +26,10 @@ /* This function will iterate over the loaded display devices until it finds the mirror device we want to load. If found, it will then copy the registry -key corresponding to the device to the context and returns TRUE. Otherwise +key corresponding to the device to the wfi and returns TRUE. Otherwise the function returns FALSE. */ -BOOL wf_mirror_driver_find_display_device(wfInfo* context) +BOOL wf_mirror_driver_find_display_device(wfInfo* wfi) { BOOL result; BOOL devFound; @@ -52,13 +52,13 @@ BOOL wf_mirror_driver_find_display_device(wfInfo* context) if (_tcsncmp(deviceInfo.DeviceKey, DEVICE_KEY_PREFIX, deviceKeyPrefixLength) == 0) { deviceKeyLength = _tcslen(deviceInfo.DeviceKey) - deviceKeyPrefixLength; - context->deviceKey = (LPTSTR) malloc((deviceKeyLength + 1) * sizeof(TCHAR)); + wfi->deviceKey = (LPTSTR) malloc((deviceKeyLength + 1) * sizeof(TCHAR)); - _tcsncpy_s(context->deviceKey, deviceKeyLength + 1, + _tcsncpy_s(wfi->deviceKey, deviceKeyLength + 1, &deviceInfo.DeviceKey[deviceKeyPrefixLength], deviceKeyLength); } - _tcsncpy_s(context->deviceName, 32, deviceInfo.DeviceName, _tcslen(deviceInfo.DeviceName)); + _tcsncpy_s(wfi->deviceName, 32, deviceInfo.DeviceName, _tcslen(deviceInfo.DeviceName)); return TRUE; } @@ -70,7 +70,7 @@ BOOL wf_mirror_driver_find_display_device(wfInfo* context) /** * This function will attempt to access the the windows registry using the device - * key stored in the current context. It will attempt to read the value of the + * key stored in the current wfi. It will attempt to read the value of the * "Attach.ToDesktop" subkey and will return TRUE if the value is already set to * val. If unable to read the subkey, this function will return FALSE. If the * subkey is not set to val it will then attempt to set it to val and return TRUE. If @@ -78,7 +78,7 @@ BOOL wf_mirror_driver_find_display_device(wfInfo* context) * FALSE. */ -BOOL wf_mirror_driver_display_device_attach(wfInfo* context, DWORD mode) +BOOL wf_mirror_driver_display_device_attach(wfInfo* wfi, DWORD mode) { HKEY hKey; LONG status; @@ -86,7 +86,7 @@ BOOL wf_mirror_driver_display_device_attach(wfInfo* context, DWORD mode) DWORD dwSize; DWORD dwValue; - status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, context->deviceKey, + status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, wfi->deviceKey, 0, KEY_READ | KEY_WOW64_64KEY, &hKey); if (status != ERROR_SUCCESS) @@ -170,7 +170,7 @@ void wf_mirror_driver_print_display_change_status(LONG status) * If unload is nonzero then the the driver will be asked to remove itself. */ -BOOL wf_mirror_driver_update(wfInfo* context, int unload) +BOOL wf_mirror_driver_update(wfInfo* wfi, int unload) { HDC dc; BOOL status; @@ -182,20 +182,25 @@ BOOL wf_mirror_driver_update(wfInfo* context, int unload) if (!unload) { + //first let's get the virtual screen dimentions + wfi->virtscreen_width = GetSystemMetrics(SM_CXVIRTUALSCREEN); + wfi->virtscreen_height = GetSystemMetrics(SM_CYVIRTUALSCREEN); + /* * Will have to come back to this for supporting non primary displays and multimonitor setups */ - dc = GetDC(NULL); - context->width = GetDeviceCaps(dc, HORZRES); - context->height = GetDeviceCaps(dc, VERTRES); - context->bitsPerPixel = GetDeviceCaps(dc, BITSPIXEL); - ReleaseDC(NULL, dc); + /*dc = GetDC(NULL); + wfi->servscreen_width = GetDeviceCaps(dc, HORZRES); + wfi->servscreen_height = GetDeviceCaps(dc, VERTRES); + wfi->bitsPerPixel = GetDeviceCaps(dc, BITSPIXEL); + ReleaseDC(NULL, dc);*/ + } else { - context->width = 0; - context->height = 0; - context->bitsPerPixel = 0; + wfi->servscreen_width = 0; + wfi->servscreen_height = 0; + wfi->bitsPerPixel = 0; } deviceMode = (DEVMODE*) malloc(sizeof(DEVMODE) + EXT_DEVMODE_SIZE_MAX); @@ -210,17 +215,17 @@ BOOL wf_mirror_driver_update(wfInfo* context, int unload) deviceMode->dmSize = sizeof(DEVMODE); deviceMode->dmDriverExtra = drvExtraSaved; - deviceMode->dmPelsWidth = context->width; - deviceMode->dmPelsHeight = context->height; - deviceMode->dmBitsPerPel = context->bitsPerPixel; - deviceMode->dmPosition.x = 0; - deviceMode->dmPosition.y = 0; + deviceMode->dmPelsWidth = wfi->virtscreen_width; + deviceMode->dmPelsHeight = wfi->virtscreen_height; + deviceMode->dmBitsPerPel = wfi->bitsPerPixel; + deviceMode->dmPosition.x = wfi->servscreen_xoffset; + deviceMode->dmPosition.y = wfi->servscreen_yoffset; deviceMode->dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_POSITION; - _tcsncpy_s(deviceMode->dmDeviceName, 32, context->deviceName, _tcslen(context->deviceName)); + _tcsncpy_s(deviceMode->dmDeviceName, 32, wfi->deviceName, _tcslen(wfi->deviceName)); - disp_change_status = ChangeDisplaySettingsEx(context->deviceName, deviceMode, NULL, CDS_UPDATEREGISTRY, NULL); + disp_change_status = ChangeDisplaySettingsEx(wfi->deviceName, deviceMode, NULL, CDS_UPDATEREGISTRY, NULL); status = (disp_change_status == DISP_CHANGE_SUCCESSFUL) ? TRUE : FALSE; @@ -230,50 +235,50 @@ BOOL wf_mirror_driver_update(wfInfo* context, int unload) return status; } -BOOL wf_mirror_driver_map_memory(wfInfo* context) +BOOL wf_mirror_driver_map_memory(wfInfo* wfi) { int status; GETCHANGESBUF* b; - context->driverDC = CreateDC(context->deviceName, NULL, NULL, NULL); + wfi->driverDC = CreateDC(wfi->deviceName, NULL, NULL, NULL); - if (context->driverDC == NULL) + if (wfi->driverDC == NULL) { - _tprintf(_T("Could not create device driver context!\n")); + _tprintf(_T("Could not create device driver wfi!\n")); return FALSE; } - context->changeBuffer = malloc(sizeof(GETCHANGESBUF)); - ZeroMemory(context->changeBuffer, sizeof(GETCHANGESBUF)); + wfi->changeBuffer = malloc(sizeof(GETCHANGESBUF)); + ZeroMemory(wfi->changeBuffer, sizeof(GETCHANGESBUF)); - status = ExtEscape(context->driverDC, dmf_esc_usm_pipe_map, 0, 0, sizeof(GETCHANGESBUF), (LPSTR) context->changeBuffer); + status = ExtEscape(wfi->driverDC, dmf_esc_usm_pipe_map, 0, 0, sizeof(GETCHANGESBUF), (LPSTR) wfi->changeBuffer); if (status <= 0) { _tprintf(_T("Failed to map shared memory from the driver! code %d\n"), status); } - b = (GETCHANGESBUF*) context->changeBuffer; + b = (GETCHANGESBUF*) wfi->changeBuffer; return TRUE; } /* Unmap the shared memory and release the DC */ -BOOL wf_mirror_driver_cleanup(wfInfo* context) +BOOL wf_mirror_driver_cleanup(wfInfo* wfi) { int status; - status = ExtEscape(context->driverDC, dmf_esc_usm_pipe_unmap, sizeof(GETCHANGESBUF), (LPSTR) context->changeBuffer, 0, 0); + status = ExtEscape(wfi->driverDC, dmf_esc_usm_pipe_unmap, sizeof(GETCHANGESBUF), (LPSTR) wfi->changeBuffer, 0, 0); if (status <= 0) { _tprintf(_T("Failed to unmap shared memory from the driver! code %d\n"), status); } - if (context->driverDC != NULL) + if (wfi->driverDC != NULL) { - status = DeleteDC(context->driverDC); + status = DeleteDC(wfi->driverDC); if (status == 0) { @@ -281,7 +286,7 @@ BOOL wf_mirror_driver_cleanup(wfInfo* context) } } - free(context->changeBuffer); + free(wfi->changeBuffer); return TRUE; } diff --git a/server/Windows/wf_mirage.h b/server/Windows/wf_mirage.h index 9287695d2..af52ab61c 100644 --- a/server/Windows/wf_mirage.h +++ b/server/Windows/wf_mirage.h @@ -200,11 +200,11 @@ typedef struct ULONG nColorBmPalEntries; } Esc_dmf_pointer_shape_get_OUT; -BOOL wf_mirror_driver_find_display_device(wfInfo* context); -BOOL wf_mirror_driver_display_device_attach(wfInfo* context, DWORD mode); -BOOL wf_mirror_driver_update(wfInfo* context, int unload); -BOOL wf_mirror_driver_map_memory(wfInfo* context); -BOOL wf_mirror_driver_cleanup(wfInfo* context); +BOOL wf_mirror_driver_find_display_device(wfInfo* wfi); +BOOL wf_mirror_driver_display_device_attach(wfInfo* wfi, DWORD mode); +BOOL wf_mirror_driver_update(wfInfo* wfi, int unload); +BOOL wf_mirror_driver_map_memory(wfInfo* wfi); +BOOL wf_mirror_driver_cleanup(wfInfo* wfi); void wf_mirror_driver_activate(wfInfo* wfi); void wf_mirror_driver_deactivate(wfInfo* wfi); diff --git a/server/Windows/wf_peer.c b/server/Windows/wf_peer.c index 1df150553..dbce24e30 100644 --- a/server/Windows/wf_peer.c +++ b/server/Windows/wf_peer.c @@ -74,7 +74,6 @@ void wf_peer_init(freerdp_peer* client) BOOL wf_peer_post_connect(freerdp_peer* client) { int i; - HDC hdc; wfInfo* wfi; rdpSettings* settings; wfPeerContext* context = (wfPeerContext*) client->context; @@ -82,20 +81,24 @@ BOOL wf_peer_post_connect(freerdp_peer* client) wfi = context->info; settings = client->settings; - hdc = GetDC(NULL); - wfi->width = GetDeviceCaps(hdc, HORZRES); - wfi->height = GetDeviceCaps(hdc, VERTRES); - wfi->bitsPerPixel = GetDeviceCaps(hdc, BITSPIXEL); - ReleaseDC(NULL, hdc); + if ( + (get_screen_info(wfi->screenID, NULL, &wfi->servscreen_width, &wfi->servscreen_height, &wfi->bitsPerPixel) == 0) || + (wfi->servscreen_width == 0) || + (wfi->servscreen_height == 0) || + (wfi->bitsPerPixel == 0) ) + { + _tprintf(_T("postconnect: error getting screen info for screen %d\n"), wfi->screenID); + return FALSE; + } - if ((settings->DesktopWidth != wfi->width) || (settings->DesktopHeight != wfi->height)) + if ((settings->width != wfi->servscreen_width) || (settings->height != wfi->servscreen_height)) { printf("Client requested resolution %dx%d, but will resize to %dx%d\n", - settings->DesktopWidth, settings->DesktopHeight, wfi->width, wfi->height); + settings->width, settings->height, wfi->servscreen_width, wfi->servscreen_height); - settings->DesktopWidth = wfi->width; - settings->DesktopHeight = wfi->height; - settings->ColorDepth = wfi->bitsPerPixel; + settings->width = wfi->servscreen_width; + settings->height = wfi->servscreen_height; + settings->color_depth = wfi->bitsPerPixel; client->update->DesktopResize(client->update->context); } diff --git a/server/Windows/wf_rdpsnd.c b/server/Windows/wf_rdpsnd.c index 8ef5b2775..bc7039a32 100644 --- a/server/Windows/wf_rdpsnd.c +++ b/server/Windows/wf_rdpsnd.c @@ -25,6 +25,8 @@ #include #include + +#include #define CINTERFACE #include #include @@ -41,7 +43,7 @@ IDirectSoundCapture8 * cap; IDirectSoundCaptureBuffer8* capBuf; DSCBUFFERDESC dscbd; -DWORD capturePos; +DWORD lastPos; #define BYTESPERSEC 176400 @@ -107,7 +109,7 @@ static void wf_peer_rdpsnd_activated(rdpsnd_server_context* context) context->SelectFormat(context, 4); context->SetVolume(context, 0x7FFF, 0x7FFF); - capturePos = 0; + lastPos = 0; CreateThread(NULL, 0, wf_rdpsnd_thread, latestPeer, 0, NULL); @@ -189,15 +191,24 @@ BOOL wf_peer_rdpsnd_init(wfPeerContext* context) DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam) { HRESULT hr; - DWORD beg, end; + DWORD beg = 0; + DWORD end = 0; DWORD diff, rate; wfPeerContext* context; wfInfo* wfi; + VOID* pbCaptureData = NULL; + DWORD dwCaptureLength = 0; + VOID* pbCaptureData2 = NULL; + DWORD dwCaptureLength2 = 0; + VOID* pbPlayData = NULL; + DWORD dwReadPos = 0; + LONG lLockSize = 0; + wfi = wf_info_get_instance(); context = (wfPeerContext*)lpParam; - rate = 1000 / 5; + rate = 1000 / 24; _tprintf(_T("Trying to start capture\n")); hr = capBuf->lpVtbl->Start(capBuf, DSCBSTART_LOOPING); @@ -209,13 +220,15 @@ DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam) while (1) { - VOID* pbCaptureData = NULL; - DWORD dwCaptureLength; - VOID* pbCaptureData2 = NULL; - DWORD dwCaptureLength2; - VOID* pbPlayData = NULL; - DWORD dwReadPos; - LONG lLockSize; + + end = GetTickCount(); + diff = end - beg; + + if (diff < rate) + { + Sleep(rate - diff); + } + beg = GetTickCount(); if (wf_rdpsnd_lock() > 0) @@ -235,9 +248,11 @@ DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam) break; } - lLockSize = dwReadPos - capturePos;//dscbd.dwBufferBytes; + lLockSize = dwReadPos - lastPos;//dscbd.dwBufferBytes; if (lLockSize < 0) lLockSize += dscbd.dwBufferBytes; + //printf("Last, read, lock = [%d, %d, %d]\n", lastPos, dwReadPos, lLockSize); + if (lLockSize == 0) { wf_rdpsnd_unlock(); @@ -245,7 +260,7 @@ DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam) } - hr = capBuf->lpVtbl->Lock(capBuf, capturePos, lLockSize, &pbCaptureData, &dwCaptureLength, &pbCaptureData2, &dwCaptureLength2, 0L); + hr = capBuf->lpVtbl->Lock(capBuf, lastPos, lLockSize, &pbCaptureData, &dwCaptureLength, &pbCaptureData2, &dwCaptureLength2, 0L); if (FAILED(hr)) { _tprintf(_T("Failed to lock sound capture buffer\n")); @@ -271,21 +286,15 @@ DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam) } //TODO keep track of location in buffer - capturePos += dwCaptureLength; - capturePos %= dscbd.dwBufferBytes; - capturePos += dwCaptureLength2; - capturePos %= dscbd.dwBufferBytes; + lastPos += dwCaptureLength; + lastPos %= dscbd.dwBufferBytes; + lastPos += dwCaptureLength2; + lastPos %= dscbd.dwBufferBytes; wf_rdpsnd_unlock(); } - end = GetTickCount(); - diff = end - beg; - - if (diff < rate) - { - Sleep(rate - diff); - } + } _tprintf(_T("Trying to stop sound capture\n")); @@ -295,7 +304,10 @@ DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam) _tprintf(_T("Failed to stop capture\n")); } _tprintf(_T("Capture stopped\n")); + capBuf->lpVtbl->Release(capBuf); + cap->lpVtbl->Release(cap); + lastPos = 0; return 0; } diff --git a/server/Windows/wf_update.c b/server/Windows/wf_update.c index d4a5ff9d9..b4faa4d65 100644 --- a/server/Windows/wf_update.c +++ b/server/Windows/wf_update.c @@ -199,8 +199,8 @@ void wf_update_encoder_reset(wfInfo* wfi) { wfi->rfx_context = rfx_context_new(); wfi->rfx_context->mode = RLGR3; - wfi->rfx_context->width = wfi->width; - wfi->rfx_context->height = wfi->height; + wfi->rfx_context->width = wfi->servscreen_width; + wfi->rfx_context->height = wfi->servscreen_height; rfx_context_set_pixel_format(wfi->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8); wfi->s = stream_new(0xFFFF); }