Merge pull request #705 from awakecoding/windows
Windows FreeRDP Server RemoteFX Encoding
This commit is contained in:
commit
577b8e30eb
@ -1,37 +1,47 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Client
|
||||
# FreeRDP Windows Server cmake build script
|
||||
#
|
||||
# Copyright 2011 O.S. Systems Software Ltda.
|
||||
# Copyright 2011 Otavio Salvador <otavio@ossystems.com.br>
|
||||
# Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# FreeRDP: A Remote Desktop Protocol Client
|
||||
# FreeRDP Windows Server cmake build script
|
||||
#
|
||||
# Copyright 2011 O.S. Systems Software Ltda.
|
||||
# Copyright 2011 Otavio Salvador <otavio@ossystems.com.br>
|
||||
# Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
add_executable(wfreerdp-server
|
||||
wf_input.c
|
||||
wf_input.h
|
||||
wf_mirage.c
|
||||
wf_mirage.h
|
||||
wf_peer.c
|
||||
wf_peer.h
|
||||
wf_info.c
|
||||
wf_info.h
|
||||
wfreerdp.c
|
||||
wfreerdp.h)
|
||||
|
||||
if(WITH_MONOLITHIC_BUILD)
|
||||
target_link_libraries(wfreerdp-server freerdp)
|
||||
|
||||
add_executable(wfreerdp-server
|
||||
wf_input.c
|
||||
wf_input.h
|
||||
wf_peer.c
|
||||
wf_peer.h
|
||||
wfreerdp.c
|
||||
wfreerdp.h)
|
||||
|
||||
if(WITH_MONOLITHIC_BUILD)
|
||||
target_link_libraries(wfreerdp-server freerdp)
|
||||
else()
|
||||
|
||||
target_link_libraries(wfreerdp-server
|
||||
|
||||
freerdp-core
|
||||
|
||||
freerdp-utils
|
||||
|
||||
freerdp-codec
|
||||
freerdp-channels)
|
||||
endif()
|
||||
|
||||
freerdp-channels)
|
||||
|
||||
endif()
|
||||
|
302
server/Windows/wf_info.c
Normal file
302
server/Windows/wf_info.c
Normal file
@ -0,0 +1,302 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* FreeRDP Windows Server
|
||||
*
|
||||
* Copyright 2012 Corey Clayton <can.of.tuna@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/windows.h>
|
||||
|
||||
#include "wf_info.h"
|
||||
#include "wf_mirage.h"
|
||||
|
||||
wfInfo * wf_info_init(wfInfo * info)
|
||||
{
|
||||
if(!info)
|
||||
{
|
||||
info = (wfInfo*)malloc(sizeof(wfInfo)); //free this on shutdown
|
||||
memset(info, 0, sizeof(wfInfo));
|
||||
|
||||
info->mutex = CreateMutex(
|
||||
NULL, // default security attributes
|
||||
FALSE, // initially not owned
|
||||
NULL); // unnamed mutex
|
||||
|
||||
if (info->mutex == NULL)
|
||||
{
|
||||
_tprintf(_T("CreateMutex error: %d\n"), GetLastError());
|
||||
}
|
||||
|
||||
info->encodeMutex = CreateMutex(
|
||||
NULL, // default security attributes
|
||||
FALSE, // initially not owned
|
||||
NULL); // unnamed mutex
|
||||
|
||||
if (info->encodeMutex == NULL)
|
||||
{
|
||||
_tprintf(_T("CreateMutex error: %d\n"), GetLastError());
|
||||
}
|
||||
|
||||
info->can_send_mutex = CreateMutex(
|
||||
NULL, // default security attributes
|
||||
FALSE, // initially not owned
|
||||
NULL); // unnamed mutex
|
||||
|
||||
if (info->can_send_mutex == NULL)
|
||||
{
|
||||
_tprintf(_T("CreateMutex error: %d\n"), GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
void wf_info_mirror_init(wfInfo * info, wfPeerContext* context)
|
||||
{
|
||||
DWORD dRes;
|
||||
|
||||
|
||||
dRes = WaitForSingleObject(
|
||||
info->mutex, // handle to mutex
|
||||
INFINITE); // no time-out interval
|
||||
|
||||
switch(dRes)
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
if(info->subscribers == 0)
|
||||
{
|
||||
//only the first peer needs to call this.
|
||||
context->wfInfo = info;
|
||||
wf_check_disp_devices(context->wfInfo);
|
||||
wf_disp_device_set_attatch(context->wfInfo, 1);
|
||||
wf_update_mirror_drv(context->wfInfo, 0);
|
||||
wf_map_mirror_mem(context->wfInfo);
|
||||
|
||||
context->rfx_context = rfx_context_new();
|
||||
context->rfx_context->mode = RLGR3;
|
||||
context->rfx_context->width = context->wfInfo->width;
|
||||
context->rfx_context->height = context->wfInfo->height;
|
||||
|
||||
rfx_context_set_pixel_format(context->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8);
|
||||
context->s = stream_new(65536);
|
||||
|
||||
printf("Start Encoder\n");
|
||||
ReleaseMutex(info->encodeMutex);
|
||||
}
|
||||
++info->subscribers;
|
||||
|
||||
if (! ReleaseMutex(info->mutex))
|
||||
{
|
||||
_tprintf(_T("Error releasing mutex\n"));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
_tprintf(_T("Error waiting for mutex: %d\n"), dRes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//todo: i think i can replace all the context->info here with info
|
||||
//in fact it may not even care about subscribers
|
||||
void wf_info_subscriber_release(wfInfo* info, wfPeerContext* context)
|
||||
{
|
||||
DWORD dRes;
|
||||
|
||||
WaitForSingleObject(info->mutex, INFINITE);
|
||||
if (context && (info->subscribers == 1))
|
||||
{
|
||||
|
||||
dRes = WaitForSingleObject(info->encodeMutex, INFINITE);
|
||||
switch (dRes)
|
||||
{
|
||||
// The thread got ownership of the mutex
|
||||
case WAIT_OBJECT_0:
|
||||
--info->subscribers;
|
||||
//only the last peer needs to call this
|
||||
wf_mirror_cleanup(context->wfInfo);
|
||||
wf_disp_device_set_attatch(context->wfInfo, 0);
|
||||
wf_update_mirror_drv(context->wfInfo, 1);
|
||||
|
||||
stream_free(context->s);
|
||||
rfx_context_free(context->rfx_context);
|
||||
|
||||
printf("Stop encoder\n");
|
||||
break;
|
||||
|
||||
// The thread got ownership of an abandoned mutex
|
||||
// The database is in an indeterminate state
|
||||
default:
|
||||
printf("wf_info_subscriber_release: Something else happened!!! dRes = %d\n", dRes);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
--info->subscribers;
|
||||
}
|
||||
|
||||
ReleaseMutex(info->mutex);
|
||||
|
||||
/***************
|
||||
Note: if we released the last subscriber,
|
||||
block the encoder until next subscriber
|
||||
***************/
|
||||
|
||||
}
|
||||
|
||||
|
||||
BOOL wf_info_has_subscribers(wfInfo* info)
|
||||
{
|
||||
int subs;
|
||||
|
||||
WaitForSingleObject(info->mutex, INFINITE);
|
||||
subs = info->subscribers;
|
||||
ReleaseMutex(info->mutex);
|
||||
|
||||
if(info->subscribers > 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
BOOL wf_info_have_updates(wfInfo* info)
|
||||
{
|
||||
BOOL ret;
|
||||
ret = true;
|
||||
WaitForSingleObject(info->mutex, INFINITE);
|
||||
if(info->nextUpdate == info->lastUpdate)
|
||||
ret = false;
|
||||
ReleaseMutex(info->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void wf_info_updated(wfInfo* info)
|
||||
{
|
||||
|
||||
WaitForSingleObject(info->mutex, INFINITE);
|
||||
info->lastUpdate = info->nextUpdate;
|
||||
ReleaseMutex(info->mutex);
|
||||
}
|
||||
|
||||
|
||||
void wf_info_update_changes(wfInfo* info)
|
||||
{
|
||||
GETCHANGESBUF* buf;
|
||||
|
||||
WaitForSingleObject(info->mutex, INFINITE);
|
||||
buf = (GETCHANGESBUF*)info->changeBuffer;
|
||||
info->nextUpdate = buf->buffer->counter;
|
||||
ReleaseMutex(info->mutex);
|
||||
}
|
||||
|
||||
|
||||
void wf_info_find_invalid_region(wfInfo* info)
|
||||
{
|
||||
int i;
|
||||
GETCHANGESBUF* buf;
|
||||
|
||||
WaitForSingleObject(info->mutex, INFINITE);
|
||||
buf = (GETCHANGESBUF*)info->changeBuffer;
|
||||
|
||||
if(info->enc_data == false)
|
||||
{
|
||||
info->invalid_x1 = 1920;//info->width;
|
||||
info->invalid_x2 = 0;
|
||||
info->invalid_y1 = 1200;// info->height;
|
||||
info->invalid_y2 = 0;
|
||||
}
|
||||
|
||||
//printf("\tFIND = (%d, %d), (%d, %d)\n", info->invalid_x1, info->invalid_y1, info->invalid_x2, info->invalid_y2);
|
||||
for(i = info->lastUpdate; i != info->nextUpdate; i = (i+1) % MAXCHANGES_BUF )
|
||||
{
|
||||
/*printf("\t(%d, %d), (%d, %d)\n",
|
||||
buf->buffer->pointrect[i].rect.left,
|
||||
buf->buffer->pointrect[i].rect.top,
|
||||
buf->buffer->pointrect[i].rect.right,
|
||||
buf->buffer->pointrect[i].rect.bottom);
|
||||
*/
|
||||
info->invalid_x1 = min(info->invalid_x1, buf->buffer->pointrect[i].rect.left);
|
||||
info->invalid_x2 = max(info->invalid_x2, buf->buffer->pointrect[i].rect.right);
|
||||
info->invalid_y1 = min(info->invalid_y1, buf->buffer->pointrect[i].rect.top);
|
||||
info->invalid_y2 = max(info->invalid_y2, buf->buffer->pointrect[i].rect.bottom);
|
||||
}
|
||||
ReleaseMutex(info->mutex);
|
||||
}
|
||||
|
||||
|
||||
void wf_info_clear_invalid_region(wfInfo* info)
|
||||
{
|
||||
|
||||
WaitForSingleObject(info->mutex, INFINITE);
|
||||
info->lastUpdate = info->nextUpdate;
|
||||
info->invalid_x1 = info->width;
|
||||
info->invalid_x2 = 0;
|
||||
info->invalid_y1 = info->height;
|
||||
info->invalid_y2 = 0;
|
||||
ReleaseMutex(info->mutex);
|
||||
}
|
||||
|
||||
BOOL wf_info_have_invalid_region(wfInfo* info)
|
||||
{
|
||||
if((info->invalid_x1 >= info->invalid_x2) || (info->invalid_y1 >= info->invalid_y2))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
int wf_info_get_height(wfInfo* info)
|
||||
{
|
||||
int ret;
|
||||
|
||||
WaitForSingleObject(info->mutex, INFINITE);
|
||||
ret = info->height;
|
||||
ReleaseMutex(info->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wf_info_get_width(wfInfo* info)
|
||||
{
|
||||
int ret;
|
||||
|
||||
WaitForSingleObject(info->mutex, INFINITE);
|
||||
ret = info->width;
|
||||
ReleaseMutex(info->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wf_info_get_thread_count(wfInfo* info)
|
||||
{
|
||||
int ret;
|
||||
WaitForSingleObject(info->mutex, INFINITE);
|
||||
ret = info->threadCnt;
|
||||
ReleaseMutex(info->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void wf_info_set_thread_count(wfInfo* info, int count)
|
||||
{
|
||||
|
||||
WaitForSingleObject(info->mutex, INFINITE);
|
||||
info->threadCnt = count;
|
||||
ReleaseMutex(info->mutex);
|
||||
}
|
76
server/Windows/wf_info.h
Normal file
76
server/Windows/wf_info.h
Normal file
@ -0,0 +1,76 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* FreeRDP Windows Server
|
||||
*
|
||||
* Copyright 2012 Corey Clayton <can.of.tuna@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WF_INFO_H
|
||||
#define WF_INFO_H
|
||||
|
||||
//#include "wfreerdp.h"
|
||||
|
||||
struct wf_peer_context;
|
||||
typedef struct wf_peer_context wfPeerContext;
|
||||
|
||||
struct wf_info
|
||||
{
|
||||
HDC driverDC;
|
||||
BOOL activated;
|
||||
void* changeBuffer;
|
||||
LPTSTR deviceKey;
|
||||
TCHAR deviceName[32];
|
||||
int subscribers;
|
||||
int threadCnt;
|
||||
int height;
|
||||
int width;
|
||||
int bitsPerPix;
|
||||
|
||||
HANDLE mutex, encodeMutex, can_send_mutex;
|
||||
|
||||
unsigned long lastUpdate;
|
||||
unsigned long nextUpdate;
|
||||
|
||||
long invalid_x1;
|
||||
long invalid_y1;
|
||||
|
||||
long invalid_x2;
|
||||
long invalid_y2;
|
||||
|
||||
BOOL enc_data;
|
||||
};
|
||||
typedef struct wf_info wfInfo;
|
||||
|
||||
wfInfo* wf_info_init(wfInfo* info);
|
||||
void wf_info_mirror_init(wfInfo* info, wfPeerContext* context);
|
||||
void wf_info_subscriber_release(wfInfo* info, wfPeerContext* context);
|
||||
|
||||
int wf_info_get_thread_count(wfInfo* info);
|
||||
void wf_info_set_thread_count(wfInfo* info, int count);
|
||||
|
||||
BOOL wf_info_has_subscribers(wfInfo* info);
|
||||
BOOL wf_info_have_updates(wfInfo* info);
|
||||
void wf_info_updated(wfInfo* info);
|
||||
void wf_info_update_changes(wfInfo* info);
|
||||
void wf_info_find_invalid_region(wfInfo* info);
|
||||
void wf_info_clear_invalid_region(wfInfo* info);
|
||||
BOOL wf_info_have_invalid_region(wfInfo* info);
|
||||
|
||||
int wf_info_get_height(wfInfo* info);
|
||||
int wf_info_get_width(wfInfo* info);
|
||||
|
||||
|
||||
|
||||
#endif
|
310
server/Windows/wf_mirage.c
Normal file
310
server/Windows/wf_mirage.c
Normal file
@ -0,0 +1,310 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* FreeRDP Windows Server
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/windows.h>
|
||||
|
||||
#include "wf_mirage.h"
|
||||
|
||||
#define DEVICE_KEY_PREFIX _T("\\Registry\\Machine\\")
|
||||
/*
|
||||
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
|
||||
the function returns false.
|
||||
*/
|
||||
BOOL wf_check_disp_devices(wfInfo* context)
|
||||
{
|
||||
BOOL result, devFound;
|
||||
DWORD deviceNumber;
|
||||
DISPLAY_DEVICE deviceInfo;
|
||||
|
||||
devFound = false;
|
||||
deviceNumber = 0;
|
||||
deviceInfo.cb = sizeof(deviceInfo);
|
||||
|
||||
printf("Detecting display devices:\n");
|
||||
|
||||
while (result = EnumDisplayDevices(NULL, deviceNumber, &deviceInfo, 0))
|
||||
{
|
||||
_tprintf(_T("\t%s\n"), deviceInfo.DeviceString);
|
||||
|
||||
if (_tcscmp(deviceInfo.DeviceString, _T("Mirage Driver")) == 0)
|
||||
{
|
||||
int deviceKeyLength;
|
||||
int deviceKeyPrefixLength;
|
||||
|
||||
_tprintf(_T("\n\nFound our target of interest!\n"));
|
||||
|
||||
deviceKeyPrefixLength = _tcslen(DEVICE_KEY_PREFIX);
|
||||
|
||||
if (_tcsncmp(deviceInfo.DeviceKey, DEVICE_KEY_PREFIX, deviceKeyPrefixLength) == 0)
|
||||
{
|
||||
deviceKeyLength = _tcslen(deviceInfo.DeviceKey) - deviceKeyPrefixLength;
|
||||
context->deviceKey = (LPTSTR) malloc((deviceKeyLength + 1) * sizeof(TCHAR));
|
||||
|
||||
_tcsncpy_s(context->deviceKey, deviceKeyLength + 1,
|
||||
&deviceInfo.DeviceKey[deviceKeyPrefixLength], deviceKeyLength);
|
||||
|
||||
_tprintf(_T("DeviceKey: %s\n"), context->deviceKey);
|
||||
}
|
||||
|
||||
_tcsncpy_s(context->deviceName, 32, deviceInfo.DeviceName, _tcslen(deviceInfo.DeviceName));
|
||||
return true;
|
||||
}
|
||||
|
||||
deviceNumber++;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
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
|
||||
"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
|
||||
unsuccessful or an unexpected value is encountered, the function returns
|
||||
false.
|
||||
*/
|
||||
BOOL wf_disp_device_set_attatch(wfInfo* context, DWORD val)
|
||||
{
|
||||
LONG status;
|
||||
DWORD rtype, rdata, rdata_size;
|
||||
|
||||
_tprintf(_T("\nOpening registry key %s\n"), context->deviceKey);
|
||||
|
||||
rtype = 0;
|
||||
rdata = 0;
|
||||
rdata_size = sizeof(rdata);
|
||||
|
||||
status = RegGetValue(HKEY_LOCAL_MACHINE, context->deviceKey,
|
||||
_T("Attach.ToDesktop"), RRF_RT_REG_DWORD, &rtype, &rdata, &rdata_size);
|
||||
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
printf("Failed to read registry value.\n");
|
||||
printf("operation returned %d\n", status);
|
||||
return false;
|
||||
}
|
||||
|
||||
_tprintf(_T("type = %04X, data = %04X\n"), rtype, rdata);
|
||||
|
||||
if (rdata == (val ^ 1))
|
||||
{
|
||||
rdata = val;
|
||||
|
||||
status = RegSetKeyValue(HKEY_LOCAL_MACHINE, context->deviceKey,
|
||||
_T("Attach.ToDesktop"), REG_DWORD, &rdata, rdata_size);
|
||||
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
_tprintf(_T("Failed to write registry value.\n"));
|
||||
_tprintf(_T("operation returned %d\n"), status);
|
||||
return false;
|
||||
}
|
||||
|
||||
_tprintf(_T("Wrote subkey \"Attach.ToDesktop\" -> %04X\n\n"), rdata);
|
||||
}
|
||||
else if (rdata == val)
|
||||
{
|
||||
_tprintf(_T("\"Attach.ToDesktop\" is already set to %04X!\n"), rdata);
|
||||
}
|
||||
else
|
||||
{
|
||||
_tprintf(_T("An wild value appeared!...\nrdata=%d\n"), rdata);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
This function will attempt to apply the currently configured display settings
|
||||
in the registry to the display driver. It will return true if successful
|
||||
otherwise it returns false.
|
||||
|
||||
If unload is nonzero then the the driver will be asked to remove it self.
|
||||
*/
|
||||
BOOL wf_update_mirror_drv(wfInfo* context, int unload)
|
||||
{
|
||||
int currentScreenPixHeight, currentScreenPixWidth, currentScreenBPP;
|
||||
HDC dc;
|
||||
LONG status;
|
||||
DWORD* extHdr;
|
||||
WORD drvExtraSaved;
|
||||
DEVMODE* deviceMode;
|
||||
DWORD dmf_devmodewext_magic_sig = 0xDF20C0DE;
|
||||
TCHAR rMsg[64];
|
||||
BOOL rturn;
|
||||
|
||||
if(!unload)
|
||||
{
|
||||
/*
|
||||
Will have to come back to this for supporting non primary displays and
|
||||
multimonitor setups
|
||||
*/
|
||||
dc = GetDC(NULL);
|
||||
currentScreenPixHeight = GetDeviceCaps(dc, VERTRES);
|
||||
currentScreenPixWidth = GetDeviceCaps(dc, HORZRES);
|
||||
currentScreenBPP = GetDeviceCaps(dc, BITSPIXEL);
|
||||
ReleaseDC(NULL, dc);
|
||||
|
||||
context->height = currentScreenPixHeight;
|
||||
context->width = currentScreenPixWidth;
|
||||
context->bitsPerPix = currentScreenBPP;
|
||||
|
||||
_tprintf(_T("Detected current screen settings: %dx%dx%d\n"), currentScreenPixHeight, currentScreenPixWidth, currentScreenBPP);
|
||||
}
|
||||
else
|
||||
{
|
||||
currentScreenPixHeight = 0;
|
||||
currentScreenPixWidth = 0;
|
||||
currentScreenBPP = 0;
|
||||
}
|
||||
|
||||
deviceMode = (DEVMODE*) malloc(sizeof(DEVMODE) + EXT_DEVMODE_SIZE_MAX);
|
||||
deviceMode->dmDriverExtra = 2 * sizeof(DWORD);
|
||||
|
||||
extHdr = (DWORD*)((BYTE*) &deviceMode + sizeof(DEVMODE));
|
||||
extHdr[0] = dmf_devmodewext_magic_sig;
|
||||
extHdr[1] = 0;
|
||||
|
||||
drvExtraSaved = deviceMode->dmDriverExtra;
|
||||
memset(deviceMode, 0, sizeof(DEVMODE) + EXT_DEVMODE_SIZE_MAX);
|
||||
deviceMode->dmSize = sizeof(DEVMODE);
|
||||
deviceMode->dmDriverExtra = drvExtraSaved;
|
||||
|
||||
deviceMode->dmPelsWidth = currentScreenPixWidth;
|
||||
deviceMode->dmPelsHeight = currentScreenPixHeight;
|
||||
deviceMode->dmBitsPerPel = currentScreenBPP;
|
||||
deviceMode->dmPosition.x = 0;
|
||||
deviceMode->dmPosition.y = 0;
|
||||
|
||||
deviceMode->dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_POSITION;
|
||||
|
||||
_tcsncpy_s(deviceMode->dmDeviceName, 32, context->deviceName, _tcslen(context->deviceName));
|
||||
|
||||
status = ChangeDisplaySettingsEx(context->deviceName, deviceMode, NULL, CDS_UPDATEREGISTRY, NULL);
|
||||
|
||||
rturn = false;
|
||||
switch (status)
|
||||
{
|
||||
case DISP_CHANGE_SUCCESSFUL:
|
||||
_tprintf(_T("ChangeDisplaySettingsEx() was successfull\n"));
|
||||
rturn = true;
|
||||
break;
|
||||
|
||||
case DISP_CHANGE_BADDUALVIEW:
|
||||
_tcscpy(rMsg, _T("DISP_CHANGE_BADDUALVIEW"));
|
||||
break;
|
||||
|
||||
case DISP_CHANGE_BADFLAGS:
|
||||
_tcscpy(rMsg, _T("DISP_CHANGE_BADFLAGS"));
|
||||
break;
|
||||
|
||||
case DISP_CHANGE_BADMODE:
|
||||
_tcscpy(rMsg, _T("DISP_CHANGE_BADMODE"));
|
||||
break;
|
||||
|
||||
case DISP_CHANGE_BADPARAM:
|
||||
_tcscpy(rMsg, _T("DISP_CHANGE_BADPARAM"));
|
||||
break;
|
||||
|
||||
case DISP_CHANGE_FAILED:
|
||||
_tcscpy(rMsg, _T("DISP_CHANGE_FAILED"));
|
||||
break;
|
||||
|
||||
case DISP_CHANGE_NOTUPDATED:
|
||||
_tcscpy(rMsg, _T("DISP_CHANGE_NOTUPDATED"));
|
||||
break;
|
||||
|
||||
case DISP_CHANGE_RESTART:
|
||||
_tcscpy(rMsg, _T("DISP_CHANGE_RESTART"));
|
||||
break;
|
||||
}
|
||||
|
||||
if(!rturn)
|
||||
_tprintf(_T("ChangeDisplaySettingsEx() failed with %s, code %d\n"), rMsg, status);
|
||||
|
||||
return rturn;
|
||||
}
|
||||
|
||||
|
||||
BOOL wf_map_mirror_mem(wfInfo* context)
|
||||
{
|
||||
int status;
|
||||
GETCHANGESBUF* b;
|
||||
_tprintf(_T("\n\nCreating a device context...\n"));
|
||||
|
||||
context->driverDC = CreateDC(context->deviceName, NULL, NULL, NULL);
|
||||
|
||||
if (context->driverDC == NULL)
|
||||
{
|
||||
_tprintf(_T("Could not create device driver context!\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
context->changeBuffer = malloc(sizeof(GETCHANGESBUF));
|
||||
memset(context->changeBuffer, 0, sizeof(GETCHANGESBUF));
|
||||
|
||||
_tprintf(_T("\n\nConnecting to driver...\n"));
|
||||
status = ExtEscape(context->driverDC, dmf_esc_usm_pipe_map, 0, 0, sizeof(GETCHANGESBUF), (LPSTR) context->changeBuffer);
|
||||
|
||||
if (status <= 0)
|
||||
{
|
||||
_tprintf(_T("Failed to map shared memory from the driver! Code %d\n"), status);
|
||||
}
|
||||
|
||||
b = (GETCHANGESBUF*)context->changeBuffer;
|
||||
_tprintf(_T("ExtEscape() returned code %d\n"), status);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
Unmap the shared memory and release the DC
|
||||
*/
|
||||
BOOL wf_mirror_cleanup(wfInfo* context)
|
||||
{
|
||||
int iResult;
|
||||
|
||||
_tprintf(_T("\n\nCleaning up...\nDisconnecting driver...\n"));
|
||||
iResult = ExtEscape(context->driverDC, dmf_esc_usm_pipe_unmap, sizeof(context->changeBuffer), (LPSTR) context->changeBuffer, 0, 0);
|
||||
|
||||
if(iResult <= 0)
|
||||
{
|
||||
_tprintf(_T("Failed to unmap shared memory from the driver! Code %d\n"), iResult);
|
||||
}
|
||||
|
||||
_tprintf(_T("Releasing DC\n"));
|
||||
if(context->driverDC != NULL)
|
||||
{
|
||||
iResult = DeleteDC(context->driverDC);
|
||||
if(iResult == 0)
|
||||
{
|
||||
_tprintf(_T("Failed to release DC!\n"));
|
||||
}
|
||||
}
|
||||
|
||||
free(context->changeBuffer);
|
||||
|
||||
return true;
|
||||
}
|
209
server/Windows/wf_mirage.h
Normal file
209
server/Windows/wf_mirage.h
Normal file
@ -0,0 +1,209 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* FreeRDP Windows Server
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WF_MIRAGE_H
|
||||
#define WF_MIRAGE_H
|
||||
|
||||
#include "wfreerdp.h"
|
||||
|
||||
enum
|
||||
{
|
||||
DMF_ESCAPE_BASE_1_VB = 1030,
|
||||
DMF_ESCAPE_BASE_2_VB = 1026,
|
||||
DMF_ESCAPE_BASE_3_VB = 24
|
||||
};
|
||||
|
||||
#ifdef _WIN64
|
||||
|
||||
#define CLIENT_64BIT 0x8000
|
||||
|
||||
enum
|
||||
{
|
||||
DMF_ESCAPE_BASE_1 = CLIENT_64BIT | DMF_ESCAPE_BASE_1_VB,
|
||||
DMF_ESCAPE_BASE_2 = CLIENT_64BIT | DMF_ESCAPE_BASE_2_VB,
|
||||
DMF_ESCAPE_BASE_3 = CLIENT_64BIT | DMF_ESCAPE_BASE_3_VB,
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
enum
|
||||
{
|
||||
DMF_ESCAPE_BASE_1 = DMF_ESCAPE_BASE_1_VB,
|
||||
DMF_ESCAPE_BASE_2 = DMF_ESCAPE_BASE_2_VB,
|
||||
DMF_ESCAPE_BASE_3 = DMF_ESCAPE_BASE_3_VB,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
dmf_esc_qry_ver_info = DMF_ESCAPE_BASE_2 + 0,
|
||||
dmf_esc_usm_pipe_map = DMF_ESCAPE_BASE_1 + 0,
|
||||
dmf_esc_usm_pipe_unmap = DMF_ESCAPE_BASE_1 + 1,
|
||||
dmf_esc_test = DMF_ESCAPE_BASE_1 + 20,
|
||||
dmf_esc_usm_pipe_mapping_test = DMF_ESCAPE_BASE_1 + 21,
|
||||
dmf_esc_pointer_shape_get = DMF_ESCAPE_BASE_3,
|
||||
|
||||
} dmf_escape;
|
||||
|
||||
#define CLIP_LIMIT 50
|
||||
#define MAXCHANGES_BUF 20000
|
||||
|
||||
typedef enum
|
||||
{
|
||||
dmf_dfo_IGNORE = 0,
|
||||
dmf_dfo_FROM_SCREEN = 1,
|
||||
dmf_dfo_FROM_DIB = 2,
|
||||
dmf_dfo_TO_SCREEN = 3,
|
||||
dmf_dfo_SCREEN_SCREEN = 11,
|
||||
dmf_dfo_BLIT = 12,
|
||||
dmf_dfo_SOLIDFILL = 13,
|
||||
dmf_dfo_BLEND = 14,
|
||||
dmf_dfo_TRANS = 15,
|
||||
dmf_dfo_PLG = 17,
|
||||
dmf_dfo_TEXTOUT = 18,
|
||||
dmf_dfo_Ptr_Shape = 19,
|
||||
dmf_dfo_Ptr_Engage = 48,
|
||||
dmf_dfo_Ptr_Avert = 49,
|
||||
dmf_dfn_assert_on = 64,
|
||||
dmf_dfn_assert_off = 65,
|
||||
} dmf_UpdEvent;
|
||||
|
||||
#define NOCACHE 1
|
||||
#define OLDCACHE 2
|
||||
#define NEWCACHE 3
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ULONG type;
|
||||
RECT rect;
|
||||
#ifndef DFMIRAGE_LEAN
|
||||
RECT origrect;
|
||||
POINT point;
|
||||
ULONG color;
|
||||
ULONG refcolor;
|
||||
#endif
|
||||
} CHANGES_RECORD;
|
||||
|
||||
typedef CHANGES_RECORD* PCHANGES_RECORD;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ULONG counter;
|
||||
CHANGES_RECORD pointrect[MAXCHANGES_BUF];
|
||||
} CHANGES_BUF;
|
||||
|
||||
#define EXT_DEVMODE_SIZE_MAX 3072
|
||||
#define DMF_PIPE_SEC_SIZE_DEFAULT ALIGN64K(sizeof(CHANGES_BUF))
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CHANGES_BUF* buffer;
|
||||
PVOID Userbuffer;
|
||||
} GETCHANGESBUF;
|
||||
|
||||
#define dmf_sprb_ERRORMASK 0x07FF
|
||||
#define dmf_sprb_STRICTSESSION_AFF 0x1FFF
|
||||
|
||||
typedef enum
|
||||
{
|
||||
dmf_sprb_internal_error = 0x0001,
|
||||
dmf_sprb_miniport_gen_error = 0x0004,
|
||||
dmf_sprb_memory_alloc_failed = 0x0008,
|
||||
dmf_sprb_pipe_buff_overflow = 0x0010,
|
||||
dmf_sprb_pipe_buff_insufficient = 0x0020,
|
||||
dmf_sprb_pipe_not_ready = 0x0040,
|
||||
dmf_sprb_gdi_err = 0x0100,
|
||||
dmf_sprb_owner_died = 0x0400,
|
||||
dmf_sprb_tgtwnd_gone = 0x0800,
|
||||
dmf_sprb_pdev_detached = 0x2000,
|
||||
} dmf_session_prob_status;
|
||||
|
||||
#define DMF_ESC_RET_FAILF 0x80000000
|
||||
#define DMF_ESC_RET_SSTMASK 0x0000FFFF
|
||||
#define DMF_ESC_RET_IMMMASK 0x7FFF0000
|
||||
|
||||
typedef enum
|
||||
{
|
||||
dmf_escret_generic_ok = 0x00010000,
|
||||
dmf_escret_bad_state = 0x00100000,
|
||||
dmf_escret_access_denied = 0x00200000,
|
||||
dmf_escret_bad_buffer_size = 0x00400000,
|
||||
dmf_escret_internal_err = 0x00800000,
|
||||
dmf_escret_out_of_memory = 0x02000000,
|
||||
dmf_escret_already_connected = 0x04000000,
|
||||
dmf_escret_oh_boy_too_late = 0x08000000,
|
||||
dmf_escret_bad_window = 0x10000000,
|
||||
dmf_escret_drv_ver_higher = 0x20000000,
|
||||
dmf_escret_drv_ver_lower = 0x40000000,
|
||||
} dmf_esc_retcode;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ULONG cbSize;
|
||||
ULONG app_actual_version;
|
||||
ULONG display_minreq_version;
|
||||
ULONG connect_options;
|
||||
} Esc_dmf_Qvi_IN;
|
||||
|
||||
enum
|
||||
{
|
||||
esc_qvi_prod_name_max = 16,
|
||||
};
|
||||
|
||||
#define ESC_QVI_PROD_MIRAGE "MIRAGE"
|
||||
#define ESC_QVI_PROD_QUASAR "QUASAR"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ULONG cbSize;
|
||||
ULONG display_actual_version;
|
||||
ULONG miniport_actual_version;
|
||||
ULONG app_minreq_version;
|
||||
ULONG display_buildno;
|
||||
ULONG miniport_buildno;
|
||||
char prod_name[esc_qvi_prod_name_max];
|
||||
} Esc_dmf_Qvi_OUT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ULONG cbSize;
|
||||
char* pDstBmBuf;
|
||||
ULONG nDstBmBufSize;
|
||||
} Esc_dmf_pointer_shape_get_IN;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ULONG cbSize;
|
||||
POINTL BmSize;
|
||||
char* pMaskBm;
|
||||
ULONG nMaskBmSize;
|
||||
char* pColorBm;
|
||||
ULONG nColorBmSize;
|
||||
char* pColorBmPal;
|
||||
ULONG nColorBmPalEntries;
|
||||
} Esc_dmf_pointer_shape_get_OUT;
|
||||
|
||||
BOOL wf_check_disp_devices(wfInfo* context);
|
||||
BOOL wf_disp_device_set_attatch(wfInfo* context, DWORD val);
|
||||
BOOL wf_update_mirror_drv(wfInfo* context, int unload);
|
||||
BOOL wf_map_mirror_mem(wfInfo* context);
|
||||
BOOL wf_mirror_cleanup(wfInfo* context);
|
||||
|
||||
#endif /* WF_MIRAGE_H */
|
@ -1,91 +1,292 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* FreeRDP Windows Server
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <freerdp/listener.h>
|
||||
|
||||
#include "wf_peer.h"
|
||||
|
||||
void wf_peer_context_new(freerdp_peer* client, wfPeerContext* context)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void wf_peer_context_free(freerdp_peer* client, wfPeerContext* context)
|
||||
{
|
||||
if (context)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void wf_peer_init(freerdp_peer* client)
|
||||
{
|
||||
client->context_size = sizeof(wfPeerContext);
|
||||
client->ContextNew = (psPeerContextNew) wf_peer_context_new;
|
||||
client->ContextFree = (psPeerContextFree) wf_peer_context_free;
|
||||
freerdp_peer_context_new(client);
|
||||
}
|
||||
|
||||
boolean wf_peer_post_connect(freerdp_peer* client)
|
||||
{
|
||||
wfPeerContext* context = (wfPeerContext*) client->context;
|
||||
|
||||
/**
|
||||
* This callback is called when the entire connection sequence is done, i.e. we've received the
|
||||
* Font List PDU from the client and sent out the Font Map PDU.
|
||||
* The server may start sending graphics output and receiving keyboard/mouse input after this
|
||||
* callback returns.
|
||||
*/
|
||||
|
||||
printf("Client %s is activated (osMajorType %d osMinorType %d)", client->local ? "(local)" : client->hostname,
|
||||
client->settings->os_major_type, client->settings->os_minor_type);
|
||||
|
||||
if (client->settings->autologon)
|
||||
{
|
||||
printf(" and wants to login automatically as %s\\%s",
|
||||
client->settings->domain ? client->settings->domain : "",
|
||||
client->settings->username);
|
||||
|
||||
/* A real server may perform OS login here if NLA is not executed previously. */
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf("Client requested desktop: %dx%dx%d\n",
|
||||
client->settings->width, client->settings->height, client->settings->color_depth);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean wf_peer_activate(freerdp_peer* client)
|
||||
{
|
||||
wfPeerContext* context = (wfPeerContext*) client->context;
|
||||
|
||||
context->activated = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void wf_peer_synchronize_event(rdpInput* input, uint32 flags)
|
||||
{
|
||||
|
||||
}
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* FreeRDP Windows Server
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/windows.h>
|
||||
|
||||
#include <freerdp/listener.h>
|
||||
#include <freerdp/utils/sleep.h>
|
||||
#include <freerdp/codec/rfx.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
|
||||
#include "wf_mirage.h"
|
||||
|
||||
#include "wf_peer.h"
|
||||
|
||||
void wf_peer_context_new(freerdp_peer* client, wfPeerContext* context)
|
||||
{
|
||||
wfInfoSingleton = wf_info_init(wfInfoSingleton);
|
||||
wf_info_mirror_init(wfInfoSingleton, context);
|
||||
}
|
||||
|
||||
void wf_peer_context_free(freerdp_peer* client, wfPeerContext* context)
|
||||
{
|
||||
wf_info_subscriber_release(wfInfoSingleton, context);
|
||||
}
|
||||
|
||||
static DWORD WINAPI wf_peer_mirror_monitor(LPVOID lpParam)
|
||||
{
|
||||
DWORD start, end, diff;
|
||||
DWORD rate;
|
||||
|
||||
freerdp_peer* client;
|
||||
|
||||
rate = 42;
|
||||
client = (freerdp_peer*)lpParam;
|
||||
|
||||
//todo: make sure we dont encode after no clients
|
||||
while(1)
|
||||
{
|
||||
|
||||
start = GetTickCount();
|
||||
|
||||
|
||||
if(wf_info_has_subscribers(wfInfoSingleton))
|
||||
{
|
||||
wf_info_update_changes(wfInfoSingleton);
|
||||
if(wf_info_have_updates(wfInfoSingleton))
|
||||
{
|
||||
//wf_info_find_invalid_region(wfInfoSingleton);
|
||||
//printf("Fake Encode!\n");
|
||||
wf_rfx_encode(client);
|
||||
}
|
||||
}
|
||||
|
||||
end = GetTickCount();
|
||||
diff = end - start;
|
||||
if(diff < rate)
|
||||
{
|
||||
//printf("sleeping for %d ms...\n", rate - diff);
|
||||
Sleep(rate - diff);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_tprintf(_T("monitor thread terminating...\n"));
|
||||
wf_info_set_thread_count(wfInfoSingleton, wf_info_get_thread_count(wfInfoSingleton) - 1 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wf_rfx_encode(freerdp_peer* client)
|
||||
{
|
||||
STREAM* s;
|
||||
wfInfo* wfi;
|
||||
RFX_RECT rect;
|
||||
rdpUpdate* update;
|
||||
wfPeerContext* wfp;
|
||||
SURFACE_BITS_COMMAND* cmd;
|
||||
GETCHANGESBUF* buf;
|
||||
long height, width;
|
||||
long offset;
|
||||
int dRes;
|
||||
|
||||
wfp = (wfPeerContext*) client->context;
|
||||
|
||||
dRes = WaitForSingleObject(wfInfoSingleton->encodeMutex, INFINITE);
|
||||
switch(dRes)
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
|
||||
wf_info_find_invalid_region(wfInfoSingleton);
|
||||
|
||||
if( (wfp->activated == false) ||
|
||||
(wf_info_has_subscribers(wfInfoSingleton) == false) ||
|
||||
!wf_info_have_invalid_region(wfInfoSingleton) ||
|
||||
(wfInfoSingleton->enc_data == true) )
|
||||
{
|
||||
ReleaseMutex(wfInfoSingleton->encodeMutex);
|
||||
break;
|
||||
}
|
||||
|
||||
update = client->update;
|
||||
cmd = &update->surface_bits_command;
|
||||
wfi = wfp->wfInfo;
|
||||
buf = (GETCHANGESBUF*)wfi->changeBuffer;
|
||||
|
||||
//printf("encode %d\n", wfi->nextUpdate - wfi->lastUpdate);
|
||||
//printf("\tinvlaid region = (%d, %d), (%d, %d)\n", wfi->invalid_x1, wfi->invalid_y1, wfi->invalid_x2, wfi->invalid_y2);
|
||||
|
||||
width = wfi->invalid_x2 - wfi->invalid_x1;
|
||||
height = wfi->invalid_y2 - wfi->invalid_y1;
|
||||
|
||||
stream_clear(wfp->s);
|
||||
stream_set_pos(wfp->s, 0);
|
||||
s = wfp->s;
|
||||
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.width = (uint16) width;
|
||||
rect.height = (uint16) height;
|
||||
|
||||
offset = (4 * wfi->invalid_x1) + (wfi->invalid_y1 * wfi->width * 4);
|
||||
|
||||
//printf("width = %d, height = %d\n", width, height);
|
||||
rfx_compose_message(wfp->rfx_context, s, &rect, 1,
|
||||
((uint8*) (buf->Userbuffer)) + offset, width, height, wfi->width * 4);
|
||||
|
||||
cmd->destLeft = wfi->invalid_x1;
|
||||
cmd->destTop = wfi->invalid_y1;
|
||||
cmd->destRight = wfi->invalid_x1 + width;
|
||||
cmd->destBottom = wfi->invalid_y1 + height;
|
||||
|
||||
|
||||
cmd->bpp = 32;
|
||||
cmd->codecID = client->settings->rfx_codec_id;
|
||||
cmd->width = width;
|
||||
cmd->height = height;
|
||||
cmd->bitmapDataLength = stream_get_length(s);
|
||||
cmd->bitmapData = stream_get_head(s);
|
||||
|
||||
wfi->enc_data = true;
|
||||
ReleaseMutex(wfInfoSingleton->encodeMutex);
|
||||
break;
|
||||
|
||||
case WAIT_TIMEOUT:
|
||||
|
||||
ReleaseMutex(wfInfoSingleton->encodeMutex);
|
||||
break;
|
||||
|
||||
case WAIT_ABANDONED:
|
||||
|
||||
printf("\n\nwf_rfx_encode: Got ownership of abandoned mutex... releasing...\n", dRes);
|
||||
ReleaseMutex(wfInfoSingleton->encodeMutex);
|
||||
break;
|
||||
default:
|
||||
printf("\n\nwf_rfx_encode: Something else happened!!! dRes = %d\n", dRes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void wf_peer_init(freerdp_peer* client)
|
||||
{
|
||||
client->context_size = sizeof(wfPeerContext);
|
||||
client->ContextNew = (psPeerContextNew) wf_peer_context_new;
|
||||
client->ContextFree = (psPeerContextFree) wf_peer_context_free;
|
||||
freerdp_peer_context_new(client);
|
||||
|
||||
if (!wf_info_get_thread_count(wfInfoSingleton))
|
||||
{
|
||||
_tprintf(_T("Trying to create a monitor thread...\n"));
|
||||
|
||||
if (CreateThread(NULL, 0, wf_peer_mirror_monitor, client, 0, NULL) != 0)
|
||||
_tprintf(_T("Created!\n"));
|
||||
|
||||
wf_info_set_thread_count(wfInfoSingleton, wf_info_get_thread_count(wfInfoSingleton) + 1 );
|
||||
}
|
||||
}
|
||||
|
||||
boolean wf_peer_post_connect(freerdp_peer* client)
|
||||
{
|
||||
wfPeerContext* context = (wfPeerContext*) client->context;
|
||||
|
||||
/**
|
||||
* This callback is called when the entire connection sequence is done, i.e. we've received the
|
||||
* Font List PDU from the client and sent out the Font Map PDU.
|
||||
* The server may start sending graphics output and receiving keyboard/mouse input after this
|
||||
* callback returns.
|
||||
*/
|
||||
|
||||
printf("Client %s is activated (osMajorType %d osMinorType %d)", client->local ? "(local)" : client->hostname,
|
||||
client->settings->os_major_type, client->settings->os_minor_type);
|
||||
|
||||
if (client->settings->autologon)
|
||||
{
|
||||
printf(" and wants to login automatically as %s\\%s",
|
||||
client->settings->domain ? client->settings->domain : "",
|
||||
client->settings->username);
|
||||
|
||||
/* A real server may perform OS login here if NLA is not executed previously. */
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf("Client requested desktop: %dx%dx%d\n",
|
||||
client->settings->width, client->settings->height, client->settings->color_depth);
|
||||
|
||||
printf("But we will try resizing to %dx%d\n",
|
||||
wf_info_get_width(wfInfoSingleton),
|
||||
wf_info_get_height(wfInfoSingleton)
|
||||
);
|
||||
|
||||
client->settings->width = wf_info_get_width(wfInfoSingleton);
|
||||
client->settings->height = wf_info_get_height(wfInfoSingleton);
|
||||
|
||||
client->update->DesktopResize(client->update->context);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean wf_peer_activate(freerdp_peer* client)
|
||||
{
|
||||
wfPeerContext* context = (wfPeerContext*) client->context;
|
||||
|
||||
context->activated = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void wf_peer_synchronize_event(rdpInput* input, uint32 flags)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void wf_peer_send_changes(rdpUpdate* update)
|
||||
{
|
||||
int dRes;
|
||||
|
||||
//are we currently encoding?
|
||||
dRes = WaitForSingleObject(wfInfoSingleton->encodeMutex, 0);
|
||||
switch(dRes)
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
//are there changes to send?
|
||||
if( !wf_info_have_updates(wfInfoSingleton) || !wf_info_have_invalid_region(wfInfoSingleton) || (wfInfoSingleton->enc_data == false) )
|
||||
{
|
||||
ReleaseMutex(wfInfoSingleton->encodeMutex);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
wf_info_updated(wfInfoSingleton);
|
||||
/*
|
||||
printf("\tSend...");
|
||||
printf("\t(%d, %d), (%d, %d) [%dx%d]\n",
|
||||
update->surface_bits_command.destLeft, update->surface_bits_command.destTop,
|
||||
update->surface_bits_command.destRight, update->surface_bits_command.destBottom,
|
||||
update->surface_bits_command.width, update->surface_bits_command.height);
|
||||
*/
|
||||
update->SurfaceBits(update->context, &update->surface_bits_command);
|
||||
//wf_info_clear_invalid_region(wfInfoSingleton);
|
||||
wfInfoSingleton->enc_data = false;
|
||||
ReleaseMutex(wfInfoSingleton->encodeMutex);
|
||||
break;
|
||||
|
||||
case WAIT_TIMEOUT:
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
printf("wf_peer_send_changes: Something else happened!!! dRes = %d\n", dRes);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,35 +1,43 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* FreeRDP Windows Server
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WF_PEER_H
|
||||
#define WF_PEER_H
|
||||
|
||||
#include "wfreerdp.h"
|
||||
|
||||
void wf_peer_context_new(freerdp_peer* client, wfPeerContext* context);
|
||||
void wf_peer_context_free(freerdp_peer* client, wfPeerContext* context);
|
||||
|
||||
void wf_peer_init(freerdp_peer* client);
|
||||
|
||||
boolean wf_peer_post_connect(freerdp_peer* client);
|
||||
boolean wf_peer_activate(freerdp_peer* client);
|
||||
|
||||
void wf_peer_synchronize_event(rdpInput* input, uint32 flags);
|
||||
|
||||
#endif /* WF_PEER_H */
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* FreeRDP Windows Server
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WF_PEER_H
|
||||
#define WF_PEER_H
|
||||
|
||||
#include "wfreerdp.h"
|
||||
#include "wf_info.h"
|
||||
|
||||
void wf_peer_context_new(freerdp_peer* client, wfPeerContext* context);
|
||||
void wf_peer_context_free(freerdp_peer* client, wfPeerContext* context);
|
||||
|
||||
void wf_peer_init(freerdp_peer* client);
|
||||
|
||||
void wf_rfx_encode(freerdp_peer* client);
|
||||
//void wf_peer_rfx_update(freerdp_peer* client, int x, int y, int width, int height);
|
||||
|
||||
boolean wf_peer_post_connect(freerdp_peer* client);
|
||||
boolean wf_peer_activate(freerdp_peer* client);
|
||||
|
||||
void wf_peer_synchronize_event(rdpInput* input, uint32 flags);
|
||||
|
||||
void wf_peer_send_changes(rdpUpdate* update);
|
||||
|
||||
wfInfo * wfInfoSingleton;
|
||||
|
||||
#endif /* WF_PEER_H */
|
||||
|
@ -1,191 +1,196 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* FreeRDP Windows Server
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/windows.h>
|
||||
|
||||
#include <freerdp/listener.h>
|
||||
#include <freerdp/utils/sleep.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/thread.h>
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
|
||||
#include "wf_input.h"
|
||||
#include "wf_peer.h"
|
||||
|
||||
#include "wfreerdp.h"
|
||||
|
||||
HANDLE g_done_event;
|
||||
int g_thread_count = 0;
|
||||
|
||||
static DWORD WINAPI wf_peer_main_loop(LPVOID lpParam)
|
||||
{
|
||||
int rcount;
|
||||
void* rfds[32];
|
||||
wfPeerContext* context;
|
||||
freerdp_peer* client = (freerdp_peer*) lpParam;
|
||||
|
||||
memset(rfds, 0, sizeof(rfds));
|
||||
|
||||
wf_peer_init(client);
|
||||
|
||||
/* Initialize the real server settings here */
|
||||
client->settings->cert_file = xstrdup("server.crt");
|
||||
client->settings->privatekey_file = xstrdup("server.key");
|
||||
|
||||
client->PostConnect = wf_peer_post_connect;
|
||||
client->Activate = wf_peer_activate;
|
||||
|
||||
client->input->SynchronizeEvent = wf_peer_synchronize_event;
|
||||
client->input->KeyboardEvent = wf_peer_keyboard_event;
|
||||
client->input->UnicodeKeyboardEvent = wf_peer_unicode_keyboard_event;
|
||||
client->input->MouseEvent = wf_peer_mouse_event;
|
||||
client->input->ExtendedMouseEvent = wf_peer_extended_mouse_event;
|
||||
|
||||
client->Initialize(client);
|
||||
context = (wfPeerContext*) client->context;
|
||||
|
||||
printf("We've got a client %s\n", client->local ? "(local)" : client->hostname);
|
||||
|
||||
while (1)
|
||||
{
|
||||
rcount = 0;
|
||||
|
||||
if (client->GetFileDescriptor(client, rfds, &rcount) != true)
|
||||
{
|
||||
printf("Failed to get FreeRDP file descriptor\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (client->CheckFileDescriptor(client) != true)
|
||||
{
|
||||
printf("Failed to check FreeRDP file descriptor\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf("Client %s disconnected.\n", client->local ? "(local)" : client->hostname);
|
||||
|
||||
client->Disconnect(client);
|
||||
freerdp_peer_context_free(client);
|
||||
freerdp_peer_free(client);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wf_peer_accepted(freerdp_listener* instance, freerdp_peer* client)
|
||||
{
|
||||
/* start peer main loop thread */
|
||||
|
||||
if (CreateThread(NULL, 0, wf_peer_main_loop, client, 0, NULL) != 0)
|
||||
g_thread_count++;
|
||||
}
|
||||
|
||||
static void wf_server_main_loop(freerdp_listener* instance)
|
||||
{
|
||||
int rcount;
|
||||
void* rfds[32];
|
||||
|
||||
memset(rfds, 0, sizeof(rfds));
|
||||
|
||||
while (1)
|
||||
{
|
||||
rcount = 0;
|
||||
|
||||
if (instance->GetFileDescriptor(instance, rfds, &rcount) != true)
|
||||
{
|
||||
printf("Failed to get FreeRDP file descriptor\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (instance->CheckFileDescriptor(instance) != true)
|
||||
{
|
||||
printf("Failed to check FreeRDP file descriptor\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
instance->Close(instance);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
HKEY hKey;
|
||||
LONG status;
|
||||
DWORD dwType;
|
||||
DWORD dwSize;
|
||||
DWORD dwValue;
|
||||
int port = 3389;
|
||||
WSADATA wsa_data;
|
||||
freerdp_listener* instance;
|
||||
|
||||
instance = freerdp_listener_new();
|
||||
|
||||
instance->PeerAccepted = wf_peer_accepted;
|
||||
|
||||
if (WSAStartup(0x101, &wsa_data) != 0)
|
||||
return 1;
|
||||
|
||||
g_done_event = CreateEvent(0, 1, 0, 0);
|
||||
|
||||
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
|
||||
|
||||
if (status == ERROR_SUCCESS)
|
||||
{
|
||||
if (RegQueryValueEx(hKey, _T("DefaultPort"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
|
||||
port = dwValue;
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
|
||||
if (argc == 2)
|
||||
port = atoi(argv[1]);
|
||||
|
||||
/* Open the server socket and start listening. */
|
||||
|
||||
if (instance->Open(instance, NULL, port))
|
||||
{
|
||||
/* Entering the server main loop. In a real server the listener can be run in its own thread. */
|
||||
wf_server_main_loop(instance);
|
||||
}
|
||||
|
||||
if (g_thread_count > 0)
|
||||
WaitForSingleObject(g_done_event, INFINITE);
|
||||
else
|
||||
MessageBox(GetConsoleWindow(),
|
||||
L"Failed to start wfreerdp-server.\n\nPlease check the debug output.",
|
||||
L"FreeRDP Error", MB_ICONSTOP);
|
||||
|
||||
WSACleanup();
|
||||
|
||||
freerdp_listener_free(instance);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* FreeRDP Windows Server
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/windows.h>
|
||||
|
||||
#include <freerdp/listener.h>
|
||||
#include <freerdp/utils/sleep.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/thread.h>
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
|
||||
#include "wf_input.h"
|
||||
#include "wf_peer.h"
|
||||
|
||||
#include "wfreerdp.h"
|
||||
|
||||
HANDLE g_done_event;
|
||||
int g_thread_count = 0;
|
||||
|
||||
BOOL derp = false;
|
||||
|
||||
static DWORD WINAPI wf_peer_main_loop(LPVOID lpParam)
|
||||
{
|
||||
int rcount;
|
||||
void* rfds[32];
|
||||
wfPeerContext* context;
|
||||
freerdp_peer* client = (freerdp_peer*) lpParam;
|
||||
|
||||
memset(rfds, 0, sizeof(rfds));
|
||||
|
||||
wf_peer_init(client);
|
||||
|
||||
/* Initialize the real server settings here */
|
||||
client->settings->cert_file = xstrdup("server.crt");
|
||||
client->settings->privatekey_file = xstrdup("server.key");
|
||||
|
||||
client->PostConnect = wf_peer_post_connect;
|
||||
client->Activate = wf_peer_activate;
|
||||
|
||||
client->input->SynchronizeEvent = wf_peer_synchronize_event;
|
||||
client->input->KeyboardEvent = wf_peer_keyboard_event;
|
||||
client->input->UnicodeKeyboardEvent = wf_peer_unicode_keyboard_event;
|
||||
client->input->MouseEvent = wf_peer_mouse_event;
|
||||
client->input->ExtendedMouseEvent = wf_peer_extended_mouse_event;
|
||||
|
||||
client->Initialize(client);
|
||||
context = (wfPeerContext*) client->context;
|
||||
|
||||
printf("We've got a client %s\n", client->local ? "(local)" : client->hostname);
|
||||
|
||||
while (1)
|
||||
{
|
||||
rcount = 0;
|
||||
|
||||
if (client->GetFileDescriptor(client, rfds, &rcount) != true)
|
||||
{
|
||||
printf("Failed to get FreeRDP file descriptor\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (client->CheckFileDescriptor(client) != true)
|
||||
{
|
||||
printf("Failed to check FreeRDP file descriptor\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if(client->activated)
|
||||
wf_peer_send_changes(client->update);
|
||||
}
|
||||
|
||||
printf("Client %s disconnected.\n", client->local ? "(local)" : client->hostname);
|
||||
|
||||
client->Disconnect(client);
|
||||
freerdp_peer_context_free(client);
|
||||
freerdp_peer_free(client);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wf_peer_accepted(freerdp_listener* instance, freerdp_peer* client)
|
||||
{
|
||||
/* start peer main loop thread */
|
||||
|
||||
if (CreateThread(NULL, 0, wf_peer_main_loop, client, 0, NULL) != 0)
|
||||
g_thread_count++;
|
||||
}
|
||||
|
||||
static void wf_server_main_loop(freerdp_listener* instance)
|
||||
{
|
||||
int rcount;
|
||||
void* rfds[32];
|
||||
|
||||
memset(rfds, 0, sizeof(rfds));
|
||||
|
||||
while (1)
|
||||
{
|
||||
rcount = 0;
|
||||
|
||||
if (instance->GetFileDescriptor(instance, rfds, &rcount) != true)
|
||||
{
|
||||
printf("Failed to get FreeRDP file descriptor\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (instance->CheckFileDescriptor(instance) != true)
|
||||
{
|
||||
printf("Failed to check FreeRDP file descriptor\n");
|
||||
break;
|
||||
}
|
||||
Sleep(20);
|
||||
}
|
||||
|
||||
instance->Close(instance);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
HKEY hKey;
|
||||
LONG status;
|
||||
DWORD dwType;
|
||||
DWORD dwSize;
|
||||
DWORD dwValue;
|
||||
int port = 3389;
|
||||
WSADATA wsa_data;
|
||||
freerdp_listener* instance;
|
||||
|
||||
instance = freerdp_listener_new();
|
||||
|
||||
instance->PeerAccepted = wf_peer_accepted;
|
||||
|
||||
if (WSAStartup(0x101, &wsa_data) != 0)
|
||||
return 1;
|
||||
|
||||
g_done_event = CreateEvent(0, 1, 0, 0);
|
||||
|
||||
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
|
||||
|
||||
if (status == ERROR_SUCCESS)
|
||||
{
|
||||
if (RegQueryValueEx(hKey, _T("DefaultPort"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
|
||||
port = dwValue;
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
|
||||
if (argc == 2)
|
||||
port = atoi(argv[1]);
|
||||
|
||||
/* Open the server socket and start listening. */
|
||||
|
||||
if (instance->Open(instance, NULL, port))
|
||||
{
|
||||
/* Entering the server main loop. In a real server the listener can be run in its own thread. */
|
||||
wf_server_main_loop(instance);
|
||||
}
|
||||
|
||||
if (g_thread_count > 0)
|
||||
WaitForSingleObject(g_done_event, INFINITE);
|
||||
else
|
||||
MessageBox(GetConsoleWindow(),
|
||||
L"Failed to start wfreerdp-server.\n\nPlease check the debug output.",
|
||||
L"FreeRDP Error", MB_ICONSTOP);
|
||||
|
||||
WSACleanup();
|
||||
|
||||
freerdp_listener_free(instance);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,32 +1,41 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* FreeRDP Windows Server
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WFREERDP_H
|
||||
#define WFREERDP_H
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
|
||||
struct wf_peer_context
|
||||
{
|
||||
rdpContext _p;
|
||||
boolean activated;
|
||||
};
|
||||
typedef struct wf_peer_context wfPeerContext;
|
||||
|
||||
#endif /* WFREERDP_H */
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* FreeRDP Windows Server
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WFREERDP_H
|
||||
#define WFREERDP_H
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/codec/rfx.h>
|
||||
#include "wf_info.h"
|
||||
|
||||
struct wf_peer_context
|
||||
{
|
||||
rdpContext _p;
|
||||
|
||||
wfInfo* wfInfo;
|
||||
boolean activated;
|
||||
RFX_CONTEXT* rfx_context;
|
||||
STREAM* s;
|
||||
|
||||
};
|
||||
typedef struct wf_peer_context wfPeerContext;
|
||||
|
||||
extern wfInfo * wfInfoSingleton;
|
||||
|
||||
#endif /* WFREERDP_H */
|
||||
|
Loading…
Reference in New Issue
Block a user