freerdp: merging with master

This commit is contained in:
Marc-André Moreau 2013-01-18 19:01:25 -05:00
commit 7ed7e1c9aa
53 changed files with 2399 additions and 453 deletions

View File

@ -426,10 +426,25 @@ if(MSVC)
install(PROGRAMS ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS}
DESTINATION ${CMAKE_INSTALL_BINDIR}
COMPONENT libraries)
set(EXTRA_DATA_DIR "pre-requisites/")
file(GLOB EXTRA_FILES "${CMAKE_SOURCE_DIR}/extra/*")
install(FILES ${EXTRA_FILES}
DESTINATION ${EXTRA_DATA_DIR}
COMPONENT extra)
set(REV_DATA_DIR "REV/")
file(GLOB REV_FILES "${CMAKE_SOURCE_DIR}/REV/*")
install(FILES ${REV_FILES}
DESTINATION ${REV_DATA_DIR}
COMPONENT rev)
endif()
endif()
set(CPACK_COMPONENTS_ALL client server libraries headers)
set(CPACK_COMPONENTS_ALL client server libraries headers extra rev)
set(CPACK_COMPONENT_CLIENT_DISPLAY_NAME "Client")
set(CPACK_COMPONENT_CLIENT_GROUP "Applications")

View File

@ -144,6 +144,7 @@ void cliprdr_process_short_format_names(cliprdrPlugin* cliprdr, STREAM* s, UINT3
}
else
{
format_name->name = NULL;
format_name->length = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) s->p, 32 / 2, &format_name->name, 0, NULL, NULL);
}

View File

@ -430,7 +430,7 @@ BOOL drive_file_query_information(DRIVE_FILE* file, UINT32 FsInformationClass, S
BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UINT32 Length, STREAM* input)
{
char* s;
char* s = NULL;
mode_t m;
UINT64 size;
int status;

View File

@ -471,7 +471,7 @@ static void drive_process_irp_query_volume_information(DRIVE_DEVICE* disk, IRP*
static void drive_process_irp_query_directory(DRIVE_DEVICE* disk, IRP* irp)
{
char* path;
char* path = NULL;
int status;
DRIVE_FILE* file;
BYTE InitialQuery;

View File

@ -72,7 +72,7 @@ typedef struct _PARALLEL_DEVICE PARALLEL_DEVICE;
static void parallel_process_irp_create(PARALLEL_DEVICE* parallel, IRP* irp)
{
char* path;
char* path = NULL;
int status;
UINT32 PathLength;

View File

@ -79,7 +79,7 @@ static BOOL serial_check_fds(SERIAL_DEVICE* serial);
static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp)
{
char* path;
char* path = NULL;
int status;
SERIAL_TTY* tty;
UINT32 PathLength;

View File

@ -544,6 +544,19 @@ void wf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits
free(tile_bitmap);
}
void wf_gdi_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surface_frame_marker)
{
wfInfo* wfi;
rdpSettings* settings;
wfi = ((wfContext*) context)->wfi;
settings = wfi->instance->settings;
if (surface_frame_marker->frameAction == SURFACECMD_FRAMEACTION_END && settings->FrameAcknowledge > 0)
{
IFCALL(wfi->instance->update->SurfaceFrameAcknowledge, context, surface_frame_marker->frameId);
}
}
void wf_gdi_register_update_callbacks(rdpUpdate* update)
{
rdpPrimaryUpdate* primary = update->primary;
@ -575,4 +588,5 @@ void wf_gdi_register_update_callbacks(rdpUpdate* update)
primary->EllipseCB = NULL;
update->SurfaceBits = wf_gdi_surface_bits;
update->SurfaceFrameMarker = wf_gdi_surface_frame_marker;
}

View File

@ -259,7 +259,7 @@ BOOL wf_pre_connect(freerdp* instance)
wfi->cursor = g_default_cursor;
wfi->fullscreen = settings->Fullscreen;
wfi->fs_toggle = wfi->fullscreen;
wfi->fs_toggle = 1;
wfi->sw_gdi = settings->SoftwareGdi;
wfi->clrconv = (HCLRCONV) malloc(sizeof(CLRCONV));
@ -279,7 +279,7 @@ BOOL wf_pre_connect(freerdp* instance)
settings->DesktopHeight = i1;
}
if (wfi->fs_toggle)
if (wfi->fullscreen)
{
settings->DesktopWidth = GetSystemMetrics(SM_CXSCREEN);
settings->DesktopHeight = GetSystemMetrics(SM_CYSCREEN);

View File

@ -880,8 +880,11 @@ void xf_gdi_ellipse_cb(rdpContext* context, ELLIPSE_CB_ORDER* ellipse_cb)
void xf_gdi_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surface_frame_marker)
{
xfInfo* xfi = ((xfContext*) context)->xfi;
xfInfo* xfi;
rdpSettings* settings;
xfi = ((xfContext*) context)->xfi;
settings = xfi->instance->settings;
switch (surface_frame_marker->frameAction)
{
case SURFACECMD_FRAMEACTION_BEGIN:
@ -906,6 +909,10 @@ void xf_gdi_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surf
gdi_InvalidateRegion(xfi->hdc, xfi->frame_x1, xfi->frame_y1,
xfi->frame_x2 - xfi->frame_x1, xfi->frame_y2 - xfi->frame_y1);
}
if (settings->FrameAcknowledge > 0)
{
IFCALL(xfi->instance->update->SurfaceFrameAcknowledge, context, surface_frame_marker->frameId);
}
break;
}
}

View File

@ -152,6 +152,7 @@ typedef void (*pSuppressOutput)(rdpContext* context, BYTE allow, RECTANGLE_16* a
typedef void (*pSurfaceCommand)(rdpContext* context, STREAM* s);
typedef void (*pSurfaceBits)(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_command);
typedef void (*pSurfaceFrameMarker)(rdpContext* context, SURFACE_FRAME_MARKER* surface_frame_marker);
typedef void (*pSurfaceFrameAcknowledge)(rdpContext* context, UINT32 frameId);
struct rdp_update
{
@ -182,7 +183,8 @@ struct rdp_update
pSurfaceCommand SurfaceCommand; /* 64 */
pSurfaceBits SurfaceBits; /* 65 */
pSurfaceFrameMarker SurfaceFrameMarker; /* 66 */
UINT32 paddingE[80 - 67]; /* 67 */
pSurfaceFrameAcknowledge SurfaceFrameAcknowledge; /* 67 */
UINT32 paddingE[80 - 68]; /* 68 */
/* internal */

View File

@ -145,9 +145,7 @@ BOOL rdp_send_server_control_cooperate_pdu(rdpRdp* rdp)
stream_write_UINT16(s, 0); /* grantId (2 bytes) */
stream_write_UINT32(s, 0); /* controlId (4 bytes) */
rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->user_id);
return TRUE;
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->user_id);
}
BOOL rdp_send_server_control_granted_pdu(rdpRdp* rdp)
@ -160,9 +158,7 @@ BOOL rdp_send_server_control_granted_pdu(rdpRdp* rdp)
stream_write_UINT16(s, rdp->mcs->user_id); /* grantId (2 bytes) */
stream_write_UINT32(s, 0x03EA); /* controlId (4 bytes) */
rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->user_id);
return TRUE;
return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->user_id);
}
BOOL rdp_send_client_control_pdu(rdpRdp* rdp, UINT16 action)
@ -288,9 +284,17 @@ BOOL rdp_recv_deactivate_all(rdpRdp* rdp, STREAM* s)
*/
if (stream_get_left(s) > 0)
{
stream_read_UINT32(s, rdp->settings->ShareId); /* shareId (4 bytes) */
stream_read_UINT16(s, lengthSourceDescriptor); /* lengthSourceDescriptor (2 bytes) */
stream_seek(s, lengthSourceDescriptor); /* sourceDescriptor (should be 0x00) */
do {
if(stream_get_left(s) < 4)
break;
stream_read_UINT32(s, rdp->settings->ShareId); /* shareId (4 bytes) */
if(stream_get_left(s) < 2)
break;
stream_read_UINT16(s, lengthSourceDescriptor); /* lengthSourceDescriptor (2 bytes) */
if(stream_get_left(s) < lengthSourceDescriptor)
break;
stream_seek(s, lengthSourceDescriptor); /* sourceDescriptor (should be 0x00) */
} while(0);
}
rdp->state = CONNECTION_STATE_CAPABILITY;

View File

@ -2147,9 +2147,7 @@ BOOL rdp_send_demand_active(rdpRdp* rdp)
rdp_write_demand_active(s, rdp->settings);
rdp_send_pdu(rdp, s, PDU_TYPE_DEMAND_ACTIVE, rdp->mcs->user_id);
return TRUE;
return rdp_send_pdu(rdp, s, PDU_TYPE_DEMAND_ACTIVE, rdp->mcs->user_id);
}
BOOL rdp_recv_confirm_active(rdpRdp* rdp, STREAM* s)

View File

@ -123,6 +123,29 @@
*
*/
static const char *certificate_read_errors[] = {
"Certificate tag",
"TBSCertificate",
"Explicit Contextual Tag [0]",
"version",
"CertificateSerialNumber",
"AlgorithmIdentifier",
"Issuer Name",
"Validity",
"Subject Name",
"SubjectPublicKeyInfo Tag",
"subjectPublicKeyInfo::AlgorithmIdentifier",
"subjectPublicKeyInfo::subjectPublicKey",
"RSAPublicKey Tag",
"modulusLength",
"zero padding",
"modulusLength",
"modulus",
"publicExponent length",
"publicExponent"
};
/**
* Read X.509 Certificate
* @param certificate certificate module
@ -137,88 +160,105 @@ BOOL certificate_read_x509_certificate(rdpCertBlob* cert, rdpCertInfo* info)
UINT32 version;
int modulus_length;
int exponent_length;
int error = 0;
s = stream_new(0);
stream_attach(s, cert->data, cert->length);
info->Modulus = 0;
if(!ber_read_sequence_tag(s, &length)) /* Certificate (SEQUENCE) */
goto error1;
error++;
if(!ber_read_sequence_tag(s, &length)) /* TBSCertificate (SEQUENCE) */
goto error1;
error++;
/* Explicit Contextual Tag [0] */
if(!ber_read_contextual_tag(s, 0, &length, TRUE))
if(!ber_read_contextual_tag(s, 0, &length, TRUE)) /* Explicit Contextual Tag [0] */
goto error1;
error++;
if(!ber_read_integer(s, &version)) /* version (INTEGER) */
goto error1;
error++;
version++;
/* serialNumber */
if(!ber_read_integer(s, NULL)) /* CertificateSerialNumber (INTEGER) */
goto error1;
error++;
/* signature */
if(!ber_read_sequence_tag(s, &length) || !stream_skip(s, length)) /* AlgorithmIdentifier (SEQUENCE) */
goto error1;
error++;
/* issuer */
if(!ber_read_sequence_tag(s, &length) || !stream_skip(s, length)) /* Name (SEQUENCE) */
goto error1;
error++;
/* validity */
if(!ber_read_sequence_tag(s, &length) || !stream_skip(s, length)) /* Validity (SEQUENCE) */
goto error1;
error++;
/* subject */
if(!ber_read_sequence_tag(s, &length) || !stream_skip(s, length)) /* Name (SEQUENCE) */
goto error1;
error++;
/* subjectPublicKeyInfo */
if(!ber_read_sequence_tag(s, &length)) /* SubjectPublicKeyInfo (SEQUENCE) */
goto error1;
error++;
/* subjectPublicKeyInfo::AlgorithmIdentifier */
if(!ber_read_sequence_tag(s, &length) || !stream_skip(s, length)) /* AlgorithmIdentifier (SEQUENCE) */
goto error1;
error++;
/* subjectPublicKeyInfo::subjectPublicKey */
if(!ber_read_bit_string(s, &length, &padding)) /* BIT_STRING */
goto error1;
error++;
/* RSAPublicKey (SEQUENCE) */
if(!ber_read_sequence_tag(s, &length)) /* SEQUENCE */
goto error1;
error++;
if(!ber_read_integer_length(s, &modulus_length)) /* modulus (INTEGER) */
goto error1;
error++;
/* skip zero padding, if any */
do
{
if(stream_get_left(s) < padding)
if(stream_get_left(s) < 1)
goto error1;
stream_peek_BYTE(s, padding);
if (padding == 0)
{
if(stream_get_left(s) < 1)
if(!stream_skip(s, 1))
goto error1;
stream_seek(s, 1);
modulus_length--;
}
}
while (padding == 0);
error++;
if(stream_get_left(s) < modulus_length)
goto error1;
info->ModulusLength = modulus_length;
info->Modulus = (BYTE*) malloc(info->ModulusLength);
stream_read(s, info->Modulus, info->ModulusLength);
error++;
if(!ber_read_integer_length(s, &exponent_length)) /* publicExponent (INTEGER) */
goto error2;
if(stream_get_left(s) < exponent_length)
error++;
if(stream_get_left(s) < exponent_length || exponent_length > 4)
goto error2;
stream_read(s, &info->exponent[4 - exponent_length], exponent_length);
crypto_reverse(info->Modulus, info->ModulusLength);
@ -232,6 +272,7 @@ error2:
free(info->Modulus);
info->Modulus = 0;
error1:
printf("error reading when reading certificate: part=%s error=%d\n", certificate_read_errors[error], error);
stream_detach(s);
stream_free(s);
return FALSE;
@ -490,7 +531,8 @@ BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* certificate,
DEBUG_CERTIFICATE("License Server Certificate");
ret = certificate_read_x509_certificate(&certificate->x509_cert_chain->array[i], &cert_info);
DEBUG_LICENSE("modulus length:%d", (int) cert_info.ModulusLength);
free(cert_info.Modulus);
if(cert_info.Modulus)
free(cert_info.Modulus);
if(!ret)
return FALSE;
}

View File

@ -337,7 +337,8 @@ static BOOL rdp_server_establish_keys(rdpRdp* rdp, STREAM* s)
return FALSE;
}
rdp_read_security_header(s, &sec_flags);
if (!rdp_read_security_header(s, &sec_flags))
return FALSE;
if ((sec_flags & SEC_EXCHANGE_PKT) == 0)
{
@ -345,7 +346,12 @@ static BOOL rdp_server_establish_keys(rdpRdp* rdp, STREAM* s)
return FALSE;
}
if(stream_get_left(s) < 4)
return FALSE;
stream_read_UINT32(s, rand_len);
if(stream_get_left(s) < rand_len + 8) /* include 8 bytes of padding */
return FALSE;
key_len = rdp->settings->RdpServerRsaKey->ModulusLength;
if (rand_len != key_len + 8)
@ -547,9 +553,7 @@ BOOL rdp_client_connect_demand_active(rdpRdp* rdp, STREAM* s)
rdp->state = CONNECTION_STATE_FINALIZATION;
update_reset_state(rdp->update);
rdp_client_connect_finalize(rdp);
return TRUE;
return rdp_client_connect_finalize(rdp);
}
BOOL rdp_client_connect_finalize(rdpRdp* rdp)

View File

@ -488,7 +488,7 @@ void gcc_write_user_data_header(STREAM* s, UINT16 type, UINT16 length)
BOOL gcc_read_client_core_data(STREAM* s, rdpSettings* settings, UINT16 blockLength)
{
char* str;
char* str = NULL;
UINT32 version;
UINT32 color_depth;
UINT16 colorDepth = 0;
@ -518,6 +518,7 @@ BOOL gcc_read_client_core_data(STREAM* s, rdpSettings* settings, UINT16 blockLen
sprintf_s(settings->ClientHostname, 31, "%s", str);
settings->ClientHostname[31] = 0;
free(str);
str = NULL;
stream_read_UINT32(s, settings->KeyboardType); /* KeyboardType */
stream_read_UINT32(s, settings->KeyboardSubType); /* KeyboardSubType */

View File

@ -439,7 +439,9 @@ BOOL rdp_recv_client_info(rdpRdp* rdp, STREAM* s)
if (!rdp_read_header(rdp, s, &length, &channelId))
return FALSE;
rdp_read_security_header(s, &securityFlags);
if (!rdp_read_security_header(s, &securityFlags))
return FALSE;
if ((securityFlags & SEC_INFO_PKT) == 0)
return FALSE;

View File

@ -932,9 +932,7 @@ BOOL license_send_valid_client_error_packet(rdpLicense* license)
license_write_binary_blob(s, license->error_info);
license_send(license, s, ERROR_ALERT);
return TRUE;
return license_send(license, s, ERROR_ALERT);
}
/**

View File

@ -532,6 +532,7 @@ BOOL mcs_send_connect_response(rdpMcs* mcs)
{
STREAM* s;
int length;
int ret;
BYTE *bm, *em;
STREAM* gcc_CCrsp;
STREAM* server_data;
@ -556,12 +557,12 @@ BOOL mcs_send_connect_response(rdpMcs* mcs)
tpdu_write_data(s);
stream_set_mark(s, em);
transport_write(mcs->transport, s);
ret = transport_write(mcs->transport, s);
stream_free(gcc_CCrsp);
stream_free(server_data);
return TRUE;
return (ret < 0) ? FALSE : TRUE;
}
/**

View File

@ -501,8 +501,10 @@ static INLINE BOOL update_read_delta_points(STREAM* s, DELTA_POINT* points, int
do {\
if (orderInfo->fieldFlags & (1 << (NO-1))) \
{ \
if (stream_get_left(s) < 1) \
if (stream_get_left(s) < 1) {\
printf("%s: error reading %s\n", __func__, #TARGET); \
return FALSE; \
} \
stream_read_BYTE(s, TARGET); \
} \
} while(0)
@ -511,8 +513,10 @@ static INLINE BOOL update_read_delta_points(STREAM* s, DELTA_POINT* points, int
do {\
if (orderInfo->fieldFlags & (1 << (NO-1))) \
{ \
if (stream_get_left(s) < 2) \
if (stream_get_left(s) < 2) { \
printf("%s: error reading %s or %s\n", __func__, #TARGET1, #TARGET2); \
return FALSE; \
} \
stream_read_BYTE(s, TARGET1); \
stream_read_BYTE(s, TARGET2); \
} \
@ -522,8 +526,10 @@ static INLINE BOOL update_read_delta_points(STREAM* s, DELTA_POINT* points, int
do {\
if (orderInfo->fieldFlags & (1 << (NO-1))) \
{ \
if (stream_get_left(s) < 2) \
if (stream_get_left(s) < 2) { \
printf("%s: error reading %s\n", __func__, #TARGET); \
return FALSE; \
} \
stream_read_UINT16(s, TARGET); \
} \
} while(0)
@ -531,26 +537,42 @@ static INLINE BOOL update_read_delta_points(STREAM* s, DELTA_POINT* points, int
do {\
if (orderInfo->fieldFlags & (1 << (NO-1))) \
{ \
if (stream_get_left(s) < 4) \
if (stream_get_left(s) < 4) { \
printf("%s: error reading %s\n", __func__, #TARGET); \
return FALSE; \
} \
stream_read_UINT32(s, TARGET); \
} \
} while(0)
#define ORDER_FIELD_COORD(NO, TARGET) \
if ((orderInfo->fieldFlags & (1 << (NO-1))) && !update_read_coord(s, &TARGET, orderInfo->deltaCoordinates)) \
return FALSE
do { \
if ((orderInfo->fieldFlags & (1 << (NO-1))) && !update_read_coord(s, &TARGET, orderInfo->deltaCoordinates)) { \
printf("%s: error reading %s\n", __func__, #TARGET); \
return FALSE; \
} \
} while(0)
#define ORDER_FIELD_COLOR(NO, TARGET) \
if ((orderInfo->fieldFlags & (1 << (NO-1))) && !update_read_color(s, &TARGET)) \
return FALSE
do { \
if ((orderInfo->fieldFlags & (1 << (NO-1))) && !update_read_color(s, &TARGET)) { \
printf("%s: error reading %s\n", __func__, #TARGET); \
return FALSE; \
} \
} while(0)
#define FIELD_SKIP_BUFFER16(s, TARGET_LEN) \
if (stream_get_left(s) < 2) \
do { \
if (stream_get_left(s) < 2) {\
printf("%s: error reading length %s\n", __func__, #TARGET_LEN); \
return FALSE; \
}\
stream_read_UINT16(s, TARGET_LEN); \
if (!stream_skip(s, TARGET_LEN)) \
return FALSE
if (!stream_skip(s, TARGET_LEN)) { \
printf("%s: error skipping %d bytes\n", __func__, TARGET_LEN); \
return FALSE; \
} \
} while(0)
/* Primary Drawing Orders */

View File

@ -135,6 +135,8 @@ static BOOL peer_recv_data_pdu(freerdp_peer* client, STREAM* s)
return FALSE;
case DATA_PDU_TYPE_FRAME_ACKNOWLEDGE:
if(stream_get_left(s) < 4)
return FALSE;
stream_read_UINT32(s, client->ack_frame_id);
break;
@ -176,7 +178,8 @@ static int peer_recv_tpkt_pdu(freerdp_peer* client, STREAM* s)
if (rdp->settings->DisableEncryption)
{
rdp_read_security_header(s, &securityFlags);
if (!rdp_read_security_header(s, &securityFlags))
return -1;
if (securityFlags & SEC_ENCRYPT)
{
@ -224,8 +227,10 @@ static int peer_recv_fastpath_pdu(freerdp_peer* client, STREAM* s)
rdp = client->context->rdp;
fastpath = rdp->fastpath;
if (!fastpath_read_header_rdp(fastpath, s, &length))
return -1;
//if (!fastpath_read_header_rdp(fastpath, s, &length))
// return -1;
fastpath_read_header_rdp(fastpath, s, &length);
if ((length == 0) || (length > stream_get_left(s)))
{
@ -235,7 +240,7 @@ static int peer_recv_fastpath_pdu(freerdp_peer* client, STREAM* s)
if (fastpath->encryptionFlags & FASTPATH_OUTPUT_ENCRYPTED)
{
if(!rdp_decrypt(rdp, s, length, (fastpath->encryptionFlags & FASTPATH_OUTPUT_SECURE_CHECKSUM) ? SEC_SECURE_CHECKSUM : 0))
if (!rdp_decrypt(rdp, s, length, (fastpath->encryptionFlags & FASTPATH_OUTPUT_SECURE_CHECKSUM) ? SEC_SECURE_CHECKSUM : 0))
return -1;
}
@ -327,7 +332,7 @@ static BOOL peer_recv_callback(rdpTransport* transport, STREAM* s, void* extra)
break;
case CONNECTION_STATE_ACTIVE:
if (!peer_recv_pdu(client, s))
if (peer_recv_pdu(client, s) < 0)
return -1;
break;

View File

@ -161,4 +161,3 @@ void update_write_surfcmd_frame_marker(STREAM* s, UINT16 frameAction, UINT32 fra
stream_write_UINT16(s, frameAction);
stream_write_UINT32(s, frameId);
}

View File

@ -76,7 +76,7 @@ void rdp_write_system_time(STREAM* s, SYSTEM_TIME* system_time)
BOOL rdp_read_client_time_zone(STREAM* s, rdpSettings* settings)
{
char* str;
char* str = NULL;
TIME_ZONE_INFO* clientTimeZone;
if (stream_get_left(s) < 172)
@ -91,6 +91,7 @@ BOOL rdp_read_client_time_zone(STREAM* s, rdpSettings* settings)
stream_seek(s, 64);
strncpy(clientTimeZone->standardName, str, sizeof(clientTimeZone->standardName));
free(str);
str = NULL;
rdp_read_system_time(s, &clientTimeZone->standardDate); /* StandardDate */
stream_read_UINT32(s, clientTimeZone->standardBias); /* StandardBias */

View File

@ -259,6 +259,9 @@ BOOL transport_accept_nla(rdpTransport* transport)
if (transport->TlsIn == NULL)
transport->TlsIn = tls_new(transport->settings);
if (transport->TlsOut == NULL)
transport->TlsOut = transport->TlsIn;
transport->layer = TRANSPORT_LAYER_TLS;
transport->TlsIn->sockfd = transport->TcpIn->sockfd;

View File

@ -508,6 +508,16 @@ static void update_send_surface_frame_marker(rdpContext* context, SURFACE_FRAME_
fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s);
}
static void update_send_frame_acknowledge(rdpContext* context, UINT32 frameId)
{
STREAM* s;
rdpRdp* rdp = context->rdp;
s = rdp_data_pdu_init(rdp);
stream_write_UINT32(s, frameId);
rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FRAME_ACKNOWLEDGE, rdp->mcs->user_id);
}
static void update_send_synchronize(rdpContext* context)
{
STREAM* s;
@ -687,6 +697,7 @@ void update_register_client_callbacks(rdpUpdate* update)
{
update->RefreshRect = update_send_refresh_rect;
update->SuppressOutput = update_send_suppress_output;
update->SurfaceFrameAcknowledge = update_send_frame_acknowledge;
}
static void* update_thread(void* arg)

View File

@ -232,14 +232,17 @@ UINT32 freerdp_keyboard_init_x11(UINT32 keyboardLayoutId, RDP_SCANCODE x11_keyco
#else
{
char* keymap;
char* xkb_layout;
char* xkb_variant;
char* xkb_layout = 0;
char* xkb_variant = 0;
if (keyboardLayoutId == 0)
{
keyboardLayoutId = freerdp_detect_keyboard_layout_from_xkb(&xkb_layout, &xkb_variant);
free(xkb_layout);
free(xkb_variant);
if (xkb_layout)
free(xkb_layout);
if (xkb_variant)
free(xkb_variant);
}
keymap = freerdp_detect_keymap_from_xkb();

View File

@ -325,7 +325,10 @@ void rail_UpdateWindow(rdpRail* rail, rdpWindow* window)
if (window->fieldFlags & WINDOW_ORDER_FIELD_TITLE)
{
if (window->title != NULL)
{
free(window->title);
window->title = NULL;
}
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) window->titleInfo.string, window->titleInfo.length / 2,
&window->title, 0, NULL, NULL);

View File

@ -34,7 +34,7 @@ UINT64 freerdp_windows_gmtime()
time_t unix_time;
UINT64 windows_time;
gmtime(&unix_time);
time(&unix_time);
windows_time = freerdp_get_windows_time_from_unix_time(unix_time);
return windows_time;

View File

@ -18,17 +18,48 @@
set(MODULE_NAME "mfreerdp-server")
set(MODULE_PREFIX "FREERDP_SERVER_MAC")
FIND_LIBRARY(CORE_VIDEO CoreVideo)
FIND_LIBRARY(CORE_GRAPHICS CoreGraphics)
FIND_LIBRARY(APP_SERVICES ApplicationServices)
FIND_LIBRARY(IOKIT IOKit)
FIND_LIBRARY(IOSURFACE IOSurface)
set(${MODULE_PREFIX}_SRCS
mfreerdp.c
mfreerdp.h
mf_audin.c
mf_audin.h
mf_rdpsnd.c
mf_rdpsnd.h)
mf_interface.c
mf_interface.h
mf_event.c
mf_event.h
mf_peer.c
mf_peer.h
mf_info.c
mf_info.h
mf_mountain_lion.c
mf_mountain_lion.h)
if(CHANNEL_AUDIN_SERVER)
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS}
mf_audin.c
mf_audin.h)
endif()
if(CHANNEL_RDPSND_SERVER)
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS}
mf_rdpsnd.c
mf_rdpsnd.h)
endif()
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-server)
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
freerdp-server
${CORE_VIDEO}
${CORE_GRAPHICS}
${APP_SERVICES}
${IOKIT}
${IOSURFACE})
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}

214
server/Mac/mf_event.c Normal file
View File

@ -0,0 +1,214 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* OS X Server Event Handling
*
* 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <freerdp/utils/memory.h>
#include "mf_event.h"
int mf_is_event_set(mfEventQueue* event_queue)
{
fd_set rfds;
int num_set;
struct timeval time;
FD_ZERO(&rfds);
FD_SET(event_queue->pipe_fd[0], &rfds);
memset(&time, 0, sizeof(time));
num_set = select(event_queue->pipe_fd[0] + 1, &rfds, 0, 0, &time);
return (num_set == 1);
}
void mf_signal_event(mfEventQueue* event_queue)
{
int length;
length = write(event_queue->pipe_fd[1], "sig", 4);
if (length != 4)
printf("mf_signal_event: error\n");
}
void mf_set_event(mfEventQueue* event_queue)
{
int length;
length = write(event_queue->pipe_fd[1], "sig", 4);
if (length != 4)
printf("mf_set_event: error\n");
}
void mf_clear_events(mfEventQueue* event_queue)
{
int length;
while (mf_is_event_set(event_queue))
{
length = read(event_queue->pipe_fd[0], &length, 4);
if (length != 4)
printf("mf_clear_event: error\n");
}
}
void mf_clear_event(mfEventQueue* event_queue)
{
int length;
length = read(event_queue->pipe_fd[0], &length, 4);
if (length != 4)
printf("mf_clear_event: error\n");
}
void mf_event_push(mfEventQueue* event_queue, mfEvent* event)
{
pthread_mutex_lock(&(event_queue->mutex));
if (event_queue->count >= event_queue->size)
{
event_queue->size *= 2;
event_queue->events = (mfEvent**) realloc((void*) event_queue->events, sizeof(mfEvent*) * event_queue->size);
}
event_queue->events[(event_queue->count)++] = event;
pthread_mutex_unlock(&(event_queue->mutex));
mf_set_event(event_queue);
}
mfEvent* mf_event_peek(mfEventQueue* event_queue)
{
mfEvent* event;
pthread_mutex_lock(&(event_queue->mutex));
if (event_queue->count < 1)
event = NULL;
else
event = event_queue->events[0];
pthread_mutex_unlock(&(event_queue->mutex));
return event;
}
mfEvent* mf_event_pop(mfEventQueue* event_queue)
{
mfEvent* event;
pthread_mutex_lock(&(event_queue->mutex));
if (event_queue->count < 1)
return NULL;
/* remove event signal */
mf_clear_event(event_queue);
event = event_queue->events[0];
(event_queue->count)--;
memmove(&event_queue->events[0], &event_queue->events[1], event_queue->count * sizeof(void*));
pthread_mutex_unlock(&(event_queue->mutex));
return event;
}
mfEventRegion* mf_event_region_new(int x, int y, int width, int height)
{
mfEventRegion* event_region = xnew(mfEventRegion);
if (event_region != NULL)
{
event_region->x = x;
event_region->y = y;
event_region->width = width;
event_region->height = height;
}
return event_region;
}
void mf_event_region_free(mfEventRegion* event_region)
{
free(event_region);
}
mfEvent* mf_event_new(int type)
{
mfEvent* event = xnew(mfEvent);
event->type = type;
return event;
}
void mf_event_free(mfEvent* event)
{
free(event);
}
mfEventQueue* mf_event_queue_new()
{
mfEventQueue* event_queue = xnew(mfEventQueue);
if (event_queue != NULL)
{
event_queue->pipe_fd[0] = -1;
event_queue->pipe_fd[1] = -1;
event_queue->size = 16;
event_queue->count = 0;
event_queue->events = (mfEvent**) xzalloc(sizeof(mfEvent*) * event_queue->size);
if (pipe(event_queue->pipe_fd) < 0)
printf("mf_event_queue_new: pipe failed\n");
pthread_mutex_init(&(event_queue->mutex), NULL);
}
return event_queue;
}
void mf_event_queue_free(mfEventQueue* event_queue)
{
if (event_queue->pipe_fd[0] != -1)
{
close(event_queue->pipe_fd[0]);
event_queue->pipe_fd[0] = -1;
}
if (event_queue->pipe_fd[1] != -1)
{
close(event_queue->pipe_fd[1]);
event_queue->pipe_fd[1] = -1;
}
pthread_mutex_destroy(&(event_queue->mutex));
}

75
server/Mac/mf_event.h Normal file
View File

@ -0,0 +1,75 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* OS X Server Event Handling
*
* 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 __MF_EVENT_H
#define __XMF_EVENT_H
typedef struct mf_event mfEvent;
typedef struct mf_event_queue mfEventQueue;
typedef struct mf_event_region mfEventRegion;
#include <pthread.h>
#include "mfreerdp.h"
//#include "mf_peer.h"
enum mf_event_type
{
MF_EVENT_TYPE_REGION,
MF_EVENT_TYPE_FRAME_TICK
};
struct mf_event
{
int type;
};
struct mf_event_queue
{
int size;
int count;
int pipe_fd[2];
mfEvent** events;
pthread_mutex_t mutex;
};
struct mf_event_region
{
int type;
int x;
int y;
int width;
int height;
};
void mf_event_push(mfEventQueue* event_queue, mfEvent* event);
mfEvent* mf_event_peek(mfEventQueue* event_queue);
mfEvent* mf_event_pop(mfEventQueue* event_queue);
mfEventRegion* mf_event_region_new(int x, int y, int width, int height);
void mf_event_region_free(mfEventRegion* event_region);
mfEvent* mf_event_new(int type);
void mf_event_free(mfEvent* event);
mfEventQueue* mf_event_queue_new();
void mf_event_queue_free(mfEventQueue* event_queue);
#endif /* __MF_EVENT_H */

308
server/Mac/mf_info.c Normal file
View File

@ -0,0 +1,308 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* FreeRDP Mac OS X 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <errno.h>
#include "mf_info.h"
#include "mf_mountain_lion.h"
//#include "mf_update.h"
static mfInfo* mfInfoInstance = NULL;
//static int _IDcount = 0;
int mf_info_lock(mfInfo* mfi)
{
int status = pthread_mutex_lock(&mfi->mutex);
switch (status) {
case 0:
return TRUE;
break;
default:
printf("mf_info_lock failed with %#X\n", status);
return -1;
break;
}
}
int mf_info_try_lock(mfInfo* mfi, UINT32 ms)
{
int status = pthread_mutex_trylock(&mfi->mutex);
switch (status) {
case 0:
return TRUE;
break;
case EBUSY:
return FALSE;
break;
default:
printf("mf_info_try_lock failed with %#X\n", status);
return -1;
break;
}
}
int mf_info_unlock(mfInfo* mfi)
{
int status = pthread_mutex_unlock(&mfi->mutex);
switch (status) {
case 0:
return TRUE;
break;
default:
printf("mf_info_unlock failed with %#X\n", status);
return -1;
break;
}
}
mfInfo* mf_info_init()
{
mfInfo* mfi;
mfi = (mfInfo*) malloc(sizeof(mfInfo));
memset(mfi, 0, sizeof(mfInfo));
if (mfi != NULL)
{
/* HKEY hKey;
LONG status;
DWORD dwType;
DWORD dwSize;
DWORD dwValue;
*/
int mutexInitStatus = pthread_mutex_init(&mfi->mutex, NULL);
if (mutexInitStatus != 0)
{
printf(_T("CreateMutex error: %#X\n"), mutexInitStatus);
}
mfi->peers = (freerdp_peer**) malloc(sizeof(freerdp_peer*) * MF_INFO_MAXPEERS);
memset(mfi->peers, 0, sizeof(freerdp_peer*) * MF_INFO_MAXPEERS);
//Set FPS
mfi->framesPerSecond = MF_INFO_DEFAULT_FPS;
/*status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
if (status == ERROR_SUCCESS)
{
if (RegQueryValueEx(hKey, _T("FramesPerSecond"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
mfi->framesPerSecond = dwValue;
}
RegCloseKey(hKey);*/
//Set input toggle
mfi->input_disabled = FALSE;
/*status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
if (status == ERROR_SUCCESS)
{
if (RegQueryValueEx(hKey, _T("DisableInput"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
{
if (dwValue != 0)
mfi->input_disabled = TRUE;
}
}
RegCloseKey(hKey);*/
}
return mfi;
}
mfInfo* mf_info_get_instance()
{
if (mfInfoInstance == NULL)
mfInfoInstance = mf_info_init();
return mfInfoInstance;
}
void mf_info_peer_register(mfInfo* mfi, mfPeerContext* context)
{
if (mf_info_lock(mfi) > 0)
{
int i;
int peerId;
if (mfi->peerCount == MF_INFO_MAXPEERS)
{
printf("TODO: socketClose on OS X\n");
//context->socketClose = TRUE;
mf_info_unlock(mfi);
return;
}
context->info = mfi;
//get the offset of the top left corner of selected screen
//EnumDisplayMonitors(NULL, NULL, mf_info_monEnumCB, 0);
//_IDcount = 0;
//initialize screen capture
if (mfi->peerCount == 0)
{
mf_mlion_display_info(&mfi->servscreen_width, &mfi->servscreen_height, &mfi->scale);
mf_mlion_screen_updates_init();
mf_mlion_start_getting_screen_updates();
}
//look trhough the array of peers until an empty slot
for(i=0; i<MF_INFO_MAXPEERS; ++i)
{
//empty index will be our peer id
if (mfi->peers[i] == NULL)
{
peerId = i;
break;
}
}
mfi->peers[peerId] = ((rdpContext*) context)->peer;
mfi->peers[peerId]->pId = peerId;
mfi->peerCount++;
printf("Registering Peer: id=%d #=%d\n", peerId, mfi->peerCount);
mf_info_unlock(mfi);
//mfreerdp_server_peer_callback_event(peerId, MF_SRV_CALLBACK_EVENT_CONNECT);
}
}
void mf_info_peer_unregister(mfInfo* mfi, mfPeerContext* context)
{
if (mf_info_lock(mfi) > 0)
{
int peerId;
peerId = ((rdpContext*) context)->peer->pId;
mfi->peers[peerId] = NULL;
mfi->peerCount--;
printf("Unregistering Peer: id=%d, #=%d\n", peerId, mfi->peerCount);
//screen capture cleanup
if (mfi->peerCount == 0)
{
mf_mlion_stop_getting_screen_updates();
}
mf_info_unlock(mfi);
//mfreerdp_server_peer_callback_event(peerId, MF_SRV_CALLBACK_EVENT_DISCONNECT);
}
}
BOOL mf_info_have_updates(mfInfo* mfi)
{
if(mfi->framesWaiting == 0)
return FALSE;
return TRUE;
}
void mf_info_update_changes(mfInfo* mfi)
{
/*#ifdef WITH_WIN8
mf_dxgi_nextFrame(mfi, mfi->framesPerSecond * 1000);
#else
GETCHANGESBUF* buf;
buf = (GETCHANGESBUF*) mfi->changeBuffer;
mfi->nextUpdate = buf->buffer->counter;
#endif*/
}
void mf_info_find_invalid_region(mfInfo* mfi)
{
mf_mlion_get_dirty_region(&mfi->invalid);
}
void mf_info_clear_invalid_region(mfInfo* mfi)
{
mf_mlion_clear_dirty_region();
mfi->invalid.height = 0;
mfi->invalid.width = 0;
}
void mf_info_invalidate_full_screen(mfInfo* mfi)
{
mfi->invalid.x = 0;
mfi->invalid.y = 0;
mfi->invalid.height = mfi->servscreen_height;
mfi->invalid.height = mfi->servscreen_width;
}
BOOL mf_info_have_invalid_region(mfInfo* mfi)
{
if (mfi->invalid.width * mfi->invalid.height == 0) {
return FALSE;
}
return TRUE;
}
void mf_info_getScreenData(mfInfo* mfi, long* width, long* height, BYTE** pBits, int* pitch)
{
*width = mfi->invalid.width / mfi->scale;
*height = mfi->invalid.height / mfi->scale;
*pitch = mfi->servscreen_width * mfi->scale * 4;
mf_mlion_get_pixelData(mfi->invalid.x / mfi->scale, mfi->invalid.y / mfi->scale, *width, *height, pBits);
*pBits = *pBits + (mfi->invalid.x * 4) + (*pitch * mfi->invalid.y);
}
/*
BOOL CALLBACK mf_info_monEnumCB(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
{
mfInfo * mfi;
mfi = mf_info_get_instance();
if(_IDcount == mfi->screenID)
{
mfi->servscreen_xoffset = lprcMonitor->left;
mfi->servscreen_yoffset = lprcMonitor->top;
}
_IDcount++;
return TRUE;
}
*/

50
server/Mac/mf_info.h Normal file
View File

@ -0,0 +1,50 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* FreeRDP Mac OS X 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 MF_INFO_H
#define MF_INFO_H
#define MF_INFO_DEFAULT_FPS 1
#define MF_INFO_MAXPEERS 1
#include <winpr/wtypes.h>
#include <freerdp/codec/rfx.h>
#include "mf_interface.h"
int mf_info_lock(mfInfo* mfi);
int mf_info_try_lock(mfInfo* mfi, UINT32 ms);
int mf_info_unlock(mfInfo* mfi);
mfInfo* mf_info_get_instance();
void mf_info_peer_register(mfInfo* mfi, mfPeerContext* context);
void mf_info_peer_unregister(mfInfo* mfi, mfPeerContext* context);
BOOL mf_info_have_updates(mfInfo* mfi);
void mf_info_update_changes(mfInfo* mfi);
void mf_info_find_invalid_region(mfInfo* mfi);
void mf_info_clear_invalid_region(mfInfo* mfi);
void mf_info_invalidate_full_screen(mfInfo* mfi);
BOOL mf_info_have_invalid_region(mfInfo* mfi);
void mf_info_getScreenData(mfInfo* mfi, long* width, long* height, BYTE** pBits, int* pitch);
//BOOL CALLBACK mf_info_monEnumCB(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData);
#endif /* mf_info_H */

View File

116
server/Mac/mf_interface.h Normal file
View File

@ -0,0 +1,116 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* FreeRDP Mac OS X Server
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* 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 MF_INTERFACE_H
#define MF_INTERFACE_H
#include <pthread.h>
#include <freerdp/codec/nsc.h>
#include <freerdp/listener.h>
#include <freerdp/utils/stream.h>
#ifdef WITH_SERVER_CHANNELS
#include <freerdp/channels/wtsvc.h>
#endif
#ifdef CHANNEL_RDPSND_SERVER
#include <freerdp/server/rdpsnd.h>
#include "mf_rdpsnd.h"
#endif
#ifdef CHANNEL_AUDIN_SERVER
#include "mf_audin.h"
#endif
typedef struct mf_info mfInfo;
typedef struct mf_peer_context mfPeerContext;
struct mf_peer_context
{
rdpContext _p;
mfInfo* info;
STREAM* s;
BOOL activated;
UINT32 frame_id;
BOOL audin_open;
RFX_CONTEXT* rfx_context;
NSC_CONTEXT* nsc_context;
#ifdef WITH_SERVER_CHANNELS
WTSVirtualChannelManager* vcm;
#endif
#ifdef CHANNEL_AUDIN_SERVER
audin_server_context* audin;
#endif
#ifdef CHANNEL_RDPSND_SERVER
rdpsnd_server_context* rdpsnd;
#endif
};
struct mf_info
{
//STREAM* s;
//screen and monitor info
UINT32 screenID;
UINT32 virtscreen_width;
UINT32 virtscreen_height;
UINT32 servscreen_width;
UINT32 servscreen_height;
UINT32 servscreen_xoffset;
UINT32 servscreen_yoffset;
//int frame_idx;
int bitsPerPixel;
//HDC driverDC;
int peerCount;
int activePeerCount;
//void* changeBuffer;
int framesPerSecond;
//LPTSTR deviceKey;
//TCHAR deviceName[32];
freerdp_peer** peers;
//BOOL mirrorDriverActive;
unsigned int framesWaiting;
UINT32 scale;
//HANDLE snd_mutex;
//BOOL snd_stop;
RFX_RECT invalid;
pthread_mutex_t mutex;
//BOOL updatePending;
//HANDLE updateEvent;
//HANDLE updateThread;
//HANDLE updateSemaphore;
//RFX_CONTEXT* rfx_context;
//unsigned long lastUpdate;
//unsigned long nextUpdate;
//SURFACE_BITS_COMMAND cmd;
BOOL input_disabled;
BOOL force_all_disconnect;
};
#endif

View File

@ -0,0 +1,306 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* OS X Server Event Handling
*
* 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 <dispatch/dispatch.h>
#include <CoreGraphics/CoreGraphics.h>
#include <CoreVideo/CoreVideo.h>
#include <IOKit/IOKitLib.h>
#include <IOSurface/IOSurface.h>
#include "mf_mountain_lion.h"
dispatch_semaphore_t region_sem;
dispatch_semaphore_t data_sem;
dispatch_queue_t screen_update_q;
CGDisplayStreamRef stream;
CGDisplayStreamUpdateRef lastUpdate = NULL;
BYTE* localBuf = NULL;
//CVPixelBufferRef pxbuffer = NULL;
//void *baseAddress = NULL;
//CGContextRef bitmapcontext = NULL;
//CGImageRef image = NULL;
BOOL ready = FALSE;
void (^streamHandler)(CGDisplayStreamFrameStatus, uint64_t, IOSurfaceRef, CGDisplayStreamUpdateRef) = ^(CGDisplayStreamFrameStatus status, uint64_t displayTime, IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef)
{
dispatch_semaphore_wait(region_sem, DISPATCH_TIME_FOREVER);
//may need to move this down
if(ready == TRUE)
{
RFX_RECT rect;
unsigned long offset_beg;
unsigned long stride;
rect.x = 0;
rect.y = 0;
rect.width = 0;
rect.height = 0;
mf_mlion_peek_dirty_region(&rect);
//lock surface
IOSurfaceLock(frameSurface, kIOSurfaceLockReadOnly, NULL);
//get pointer
void* baseAddress = IOSurfaceGetBaseAddress(frameSurface);
//copy region
stride = IOSurfaceGetBytesPerRow(frameSurface);
//memcpy(localBuf, baseAddress + offset_beg, surflen);
for(int i = 0; i < rect.height; i++)
{
offset_beg = (stride * (rect.y + i) + (rect.x * 4));
memcpy(localBuf + offset_beg,
baseAddress + offset_beg,
rect.width * 4);
}
//unlock surface
IOSurfaceUnlock(frameSurface, kIOSurfaceLockReadOnly, NULL);
ready = FALSE;
dispatch_semaphore_signal(data_sem);
}
if (status != kCGDisplayStreamFrameStatusFrameComplete)
{
//unhandled
switch(status)
{
case kCGDisplayStreamFrameStatusFrameIdle:
printf("kCGDisplayStreamFrameStatusFrameIdle\n");
break;
case kCGDisplayStreamFrameStatusStopped:
printf("kCGDisplayStreamFrameStatusStopped\n");
break;
case kCGDisplayStreamFrameStatusFrameBlank:
printf("kCGDisplayStreamFrameStatusFrameBlank\n");
break;
default:
printf("Unhandled Frame Status!!!\n");
}
}
else if (lastUpdate == NULL)
{
CFRetain(updateRef);
lastUpdate = updateRef;
}
else
{
CGDisplayStreamUpdateRef tmpRef;
tmpRef = lastUpdate;
lastUpdate = CGDisplayStreamUpdateCreateMergedUpdate(tmpRef, updateRef);
CFRelease(tmpRef);
}
dispatch_semaphore_signal(region_sem);
};
int mf_mlion_display_info(UINT32* disp_width, UINT32* disp_height, UINT32* scale)
{
CGDirectDisplayID display_id;
display_id = CGMainDisplayID();
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(display_id);
size_t pixelWidth = CGDisplayModeGetPixelWidth(mode);
//size_t pixelHeight = CGDisplayModeGetPixelHeight(mode);
size_t wide = CGDisplayPixelsWide(display_id);
size_t high = CGDisplayPixelsHigh(display_id);
CGDisplayModeRelease(mode);
*disp_width = wide;//pixelWidth;
*disp_height = high;//pixelHeight;
*scale = pixelWidth / wide;
return 0;
}
int mf_mlion_screen_updates_init()
{
printf("mf_mlion_screen_updates_init()\n");
CGDirectDisplayID display_id;
display_id = CGMainDisplayID();
screen_update_q = dispatch_queue_create("mfreerdp.server.screenUpdate", NULL);
region_sem = dispatch_semaphore_create(1);
data_sem = dispatch_semaphore_create(1);
UINT32 pixelWidth;
UINT32 pixelHeight;
UINT32 scale;
mf_mlion_display_info(&pixelWidth, &pixelHeight, &scale);
localBuf = malloc(pixelWidth * pixelHeight * 4);
stream = CGDisplayStreamCreateWithDispatchQueue(display_id,
pixelWidth,
pixelHeight,
'BGRA',
NULL,
screen_update_q,
streamHandler);
return 0;
}
int mf_mlion_start_getting_screen_updates()
{
CGError err;
err = CGDisplayStreamStart(stream);
if(err != kCGErrorSuccess)
{
printf("Failed to start displaystream!! err = %d\n", err);
return 1;
}
return 0;
}
int mf_mlion_stop_getting_screen_updates()
{
CGError err;
err = CGDisplayStreamStop(stream);
if(err != kCGErrorSuccess)
{
printf("Failed to stop displaystream!! err = %d\n", err);
return 1;
}
return 0;
return 0;
}
int mf_mlion_get_dirty_region(RFX_RECT* invalid)
{
dispatch_semaphore_wait(region_sem, DISPATCH_TIME_FOREVER);
if (lastUpdate != NULL)
{
mf_mlion_peek_dirty_region(invalid);
//CFRelease(lastUpdate);
//lastUpdate = NULL;
}
dispatch_semaphore_signal(region_sem);
return 0;
}
int mf_mlion_peek_dirty_region(RFX_RECT* invalid)
{
size_t num_rects;
CGRect dirtyRegion;
const CGRect * rects = CGDisplayStreamUpdateGetRects(lastUpdate, kCGDisplayStreamUpdateDirtyRects, &num_rects);
//printf("\trectangles: %zd\n", num_rects);
if (num_rects == 0) {
//dispatch_semaphore_signal(region_sem);
return 0;
}
dirtyRegion = *rects;
for (size_t i = 0; i < num_rects; i++)
{
dirtyRegion = CGRectUnion(dirtyRegion, *(rects+i));
}
invalid->x = dirtyRegion.origin.x;
invalid->y = dirtyRegion.origin.y;
invalid->height = dirtyRegion.size.height;
invalid->width = dirtyRegion.size.width;
return 0;
}
int mf_mlion_clear_dirty_region()
{
dispatch_semaphore_wait(region_sem, DISPATCH_TIME_FOREVER);
CFRelease(lastUpdate);
lastUpdate = NULL;
dispatch_semaphore_signal(region_sem);
return 0;
}
int mf_mlion_get_pixelData(long x, long y, long width, long height, BYTE** pxData)
{
dispatch_semaphore_wait(region_sem, DISPATCH_TIME_FOREVER);
ready = TRUE;
dispatch_semaphore_wait(data_sem, DISPATCH_TIME_FOREVER);
dispatch_semaphore_signal(region_sem);
//this second wait allows us to block until data is copied... more on this later
dispatch_semaphore_wait(data_sem, DISPATCH_TIME_FOREVER);
*pxData = localBuf;
dispatch_semaphore_signal(data_sem);
/*
if (image != NULL) {
CGImageRelease(image);
}
image = CGDisplayCreateImageForRect(
kCGDirectMainDisplay,
CGRectMake(x, y, width, height) );
CGContextDrawImage(
bitmapcontext,
CGRectMake(0, 1800 - height, width, height),
image);
*pxData = baseAddress;
*/
return 0;
}

View File

@ -0,0 +1,39 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* OS X Server Event Handling
*
* 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 MF_MLION_H
#define MF_MLION_H
#include <freerdp/codec/rfx.h>
int mf_mlion_display_info(UINT32* disp_width, UINT32* dispHeight, UINT32* scale);
int mf_mlion_screen_updates_init();
int mf_mlion_start_getting_screen_updates();
int mf_mlion_stop_getting_screen_updates();
int mf_mlion_get_dirty_region(RFX_RECT* invalid);
int mf_mlion_peek_dirty_region(RFX_RECT* invalid);
int mf_mlion_clear_dirty_region();
int mf_mlion_get_pixelData(long x, long y, long width, long height, BYTE **pxData);
#endif

608
server/Mac/mf_peer.c Normal file
View File

@ -0,0 +1,608 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* FreeRDP Mac OS X 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <freerdp/listener.h>
#include <freerdp/utils/sleep.h>
#include <freerdp/codec/rfx.h>
#include <freerdp/utils/stream.h>
#include <winpr/crt.h>
#include "mf_peer.h"
#include "mf_info.h"
#include "mf_event.h"
#include <mach/clock.h>
#include <mach/mach.h>
#include <dispatch/dispatch.h>
#include "OpenGL/OpenGL.h"
#include "OpenGL/gl.h"
#include "CoreVideo/CoreVideo.h"
//refactor these
int info_last_sec = 0;
int info_last_nsec = 0;
dispatch_source_t info_timer;
dispatch_queue_t info_queue;
mfEventQueue* info_event_queue;
CGLContextObj glContext;
CGContextRef bmp;
CGImageRef img;
BOOL mf_peer_get_fds(freerdp_peer* client, void** rfds, int* rcount)
{
if (info_event_queue->pipe_fd[0] == -1)
return TRUE;
rfds[*rcount] = (void *)(long) info_event_queue->pipe_fd[0];
(*rcount)++;
return TRUE;
}
BOOL mf_peer_check_fds(freerdp_peer* client)
{
mfPeerContext* context = (mfPeerContext*) client->context;
mfEvent* event;
//HGDI_RGN invalid_region;
if (context->activated == FALSE)
return TRUE;
event = mf_event_peek(info_event_queue);
if (event != NULL)
{
if (event->type == MF_EVENT_TYPE_REGION)
{
printf("unhandled event\n");
/*mfEventRegion* region = (mfEventRegion*) mf_event_pop(info_event_queue);
gdi_InvalidateRegion(xfp->hdc, region->x, region->y, region->width, region->height);
xf_event_region_free(region);*/
}
else if (event->type == MF_EVENT_TYPE_FRAME_TICK)
{
event = mf_event_pop(info_event_queue);
mf_peer_rfx_update(client);
mf_event_free(event);
}
}
return TRUE;
}
void mf_peer_rfx_update(freerdp_peer* client)
{
//check
mfInfo* mfi = mf_info_get_instance();
mf_info_find_invalid_region(mfi);
if (mf_info_have_invalid_region(mfi) == false) {
return;
}
long width;
long height;
int pitch;
BYTE* dataBits = NULL;
mf_info_getScreenData(mfi, &width, &height, &dataBits, &pitch);
mf_info_clear_invalid_region(mfi);
//encode
STREAM* s;
RFX_RECT rect;
rdpUpdate* update;
mfPeerContext* mfp;
SURFACE_BITS_COMMAND* cmd;
update = client->update;
mfp = (mfPeerContext*) client->context;
cmd = &update->surface_bits_command;
s = mfp->s;
stream_clear(s);
stream_set_pos(s, 0);
UINT32 x = mfi->invalid.x / mfi->scale;
UINT32 y = mfi->invalid.y / mfi->scale;
rect.x = 0;
rect.y = 0;
rect.width = width;
rect.height = height;
rfx_compose_message(mfp->rfx_context, s, &rect, 1,
(BYTE*) dataBits, rect.width, rect.height, pitch);
cmd->destLeft = x;
cmd->destTop = y;
cmd->destRight = x + rect.width;
cmd->destBottom = y + rect.height;
cmd->bpp = 32;
cmd->codecID = 3;
cmd->width = rect.width;
cmd->height = rect.height;
cmd->bitmapDataLength = stream_get_length(s);
cmd->bitmapData = stream_get_head(s);
//send
update->SurfaceBits(update->context, cmd);
//clean up
// note: need to stop getting new dirty rects until here
/*
CGColorSpaceRelease(rgbColorSpace);
CGImageRelease(image);
CGContextRelease(context);
CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
CVPixelBufferRelease(pxbuffer);
*/
}
/* Called when we have a new peer connecting */
void mf_peer_context_new(freerdp_peer* client, mfPeerContext* context)
{
context->info = mf_info_get_instance();
context->rfx_context = rfx_context_new();
context->rfx_context->mode = RLGR3;
context->rfx_context->width = client->settings->DesktopWidth;
context->rfx_context->height = client->settings->DesktopHeight;
rfx_context_set_pixel_format(context->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8);
rfx_context_set_cpu_opt(context->rfx_context, CPU_SSE2);
//context->nsc_context = nsc_context_new();
//nsc_context_set_pixel_format(context->nsc_context, RDP_PIXEL_FORMAT_B8G8R8A8);
context->s = stream_new(0xFFFF);
#ifdef WITH_SERVER_CHANNELS
context->vcm = WTSCreateVirtualChannelManager(client);
#endif
mf_info_peer_register(context->info, context);
}
/* Called after a peer disconnects */
void mf_peer_context_free(freerdp_peer* client, mfPeerContext* context)
{
if (context)
{
mf_info_peer_unregister(context->info, context);
dispatch_suspend(info_timer);
stream_free(context->s);
rfx_context_free(context->rfx_context);
//nsc_context_free(context->nsc_context);
#ifdef CHANNEL_AUDIN_SERVER
if (context->audin)
audin_server_context_free(context->audin);
#endif
#ifdef CHANNEL_RDPSND_SERVER
if (context->rdpsnd)
rdpsnd_server_context_free(context->rdpsnd);
#endif
#ifdef WITH_SERVER_CHANNELS
WTSDestroyVirtualChannelManager(context->vcm);
#endif
}
}
/* Called when a new client connects */
void mf_peer_init(freerdp_peer* client)
{
client->context_size = sizeof(mfPeerContext);
client->ContextNew = (psPeerContextNew) mf_peer_context_new;
client->ContextFree = (psPeerContextFree) mf_peer_context_free;
freerdp_peer_context_new(client);
info_event_queue = mf_event_queue_new();
info_queue = dispatch_queue_create("testing.101", DISPATCH_QUEUE_SERIAL);
info_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, info_queue);
if(info_timer)
{
//printf("created timer\n");
dispatch_source_set_timer(info_timer, DISPATCH_TIME_NOW, 33ull * NSEC_PER_MSEC, 100ull * NSEC_PER_MSEC);
dispatch_source_set_event_handler(info_timer, ^{
//printf("dispatch\n");
mfEvent* event = mf_event_new(MF_EVENT_TYPE_FRAME_TICK);
mf_event_push(info_event_queue, (mfEvent*) event);}
);
dispatch_resume(info_timer);
}
}
BOOL mf_peer_post_connect(freerdp_peer* client)
{
//mfPeerContext* context = (mfPeerContext*) client->context;
rdpSettings* settings = client->settings;
printf("Client %s is activated\n", client->hostname);
if (client->settings->AutoLogonEnabled)
{
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");
mfInfo* mfi = mf_info_get_instance();
mfi->scale = 1;
//mfi->servscreen_width = 2880 / mfi->scale;
//mfi->servscreen_height = 1800 / mfi->scale;
UINT32 bitsPerPixel = 32;
if ((settings->DesktopWidth != mfi->servscreen_width) || (settings->DesktopHeight != mfi->servscreen_height))
{
printf("Client requested resolution %dx%d, but will resize to %dx%d\n",
settings->DesktopWidth, settings->DesktopHeight, mfi->servscreen_width, mfi->servscreen_height);
}
settings->DesktopWidth = mfi->servscreen_width;
settings->DesktopHeight = mfi->servscreen_height;
settings->ColorDepth = bitsPerPixel;
client->update->DesktopResize(client->update->context);
/*printf("Client requested desktop: %dx%dx%d\n",
client->settings->DesktopWidth, client->settings->DesktopHeight, client->settings->ColorDepth);
*/
#ifdef WITH_SERVER_CHANNELS
/* Iterate all channel names requested by the client and activate those supported by the server */
int i;
for (i = 0; i < client->settings->ChannelCount; i++)
{
if (client->settings->ChannelDefArray[i].joined)
{
#ifdef CHANNEL_RDPSND_SERVER
if (strncmp(client->settings->ChannelDefArray[i].Name, "rdpsnd", 6) == 0)
{
mf_peer_rdpsnd_init(context); /* Audio Output */
}
#endif
}
}
/* Dynamic Virtual Channels */
#endif
#ifdef CHANNEL_AUDIN_SERVER
mf_peer_audin_init(context); /* Audio Input */
#endif
return TRUE;
}
BOOL mf_peer_activate(freerdp_peer* client)
{
mfPeerContext* context = (mfPeerContext*) client->context;
rfx_context_reset(context->rfx_context);
context->activated = TRUE;
return TRUE;
}
/*BOOL wf_peer_logon(freerdp_peer* client, SEC_WINNT_AUTH_IDENTITY* identity, BOOL automatic)
{
printf("PeerLogon\n");
if (automatic)
{
_tprintf(_T("Logon: User:%s Domain:%s Password:%s\n"),
identity->User, identity->Domain, identity->Password);
}
wfreerdp_server_peer_callback_event(((rdpContext*) client->context)->peer->pId, WF_SRV_CALLBACK_EVENT_AUTH);
return TRUE;
}*/
void mf_peer_synchronize_event(rdpInput* input, UINT32 flags)
{
printf("Client sent a synchronize event (flags:0x%08X)\n", flags);
}
void mf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
{
printf("Client sent a keyboard event (flags:0x%04X code:0x%04X)\n", flags, code);
UINT16 down = 0x4000;
//UINT16 up = 0x8000;
bool state_down = FALSE;
if (flags == down)
{
state_down = TRUE;
}
CGEventRef event;
event = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)code, state_down);
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);
}
void mf_peer_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
{
printf("Client sent a unicode keyboard event (flags:0x%04X code:0x%04X)\n", flags, code);
}
void mf_peer_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
{
//printf("Client sent a mouse event (flags:0x%04X pos: %d,%d)\n", flags, x, y);
}
void mf_peer_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
{
//printf("Client sent an extended mouse event (flags:0x%04X pos: %d,%d)\n", flags, x, y);
}
/*static void mf_peer_refresh_rect(rdpContext* context, BYTE count, RECTANGLE_16* areas)
{
BYTE i;
printf("Client requested to refresh:\n");
for (i = 0; i < count; i++)
{
printf(" (%d, %d) (%d, %d)\n", areas[i].left, areas[i].top, areas[i].right, areas[i].bottom);
}
}*/
static void mf_peer_suppress_output(rdpContext* context, BYTE allow, RECTANGLE_16* area)
{
if (allow > 0)
{
printf("Client restore output (%d, %d) (%d, %d).\n", area->left, area->top, area->right, area->bottom);
}
else
{
printf("Client minimized and suppress output.\n");
}
}
void mf_peer_accepted(freerdp_listener* instance, freerdp_peer* client)
{
pthread_t th;
pthread_create(&th, 0, mf_peer_main_loop, client);
pthread_detach(th);
}
/*DWORD WINAPI wf_peer_socket_listener(LPVOID lpParam)
{
int i, fds;
int rcount;
int max_fds;
void* rfds[32];
fd_set rfds_set;
wfPeerContext* context;
freerdp_peer* client = (freerdp_peer*) lpParam;
ZeroMemory(rfds, sizeof(rfds));
context = (wfPeerContext*) client->context;
printf("PeerSocketListener\n");
while (1)
{
rcount = 0;
if (client->GetFileDescriptor(client, rfds, &rcount) != TRUE)
{
printf("Failed to get peer file descriptor\n");
break;
}
max_fds = 0;
FD_ZERO(&rfds_set);
for (i = 0; i < rcount; i++)
{
fds = (int)(long)(rfds[i]);
if (fds > max_fds)
max_fds = fds;
FD_SET(fds, &rfds_set);
}
if (max_fds == 0)
break;
select(max_fds + 1, &rfds_set, NULL, NULL, NULL);
SetEvent(context->socketEvent);
WaitForSingleObject(context->socketSemaphore, INFINITE);
if (context->socketClose)
break;
}
printf("Exiting Peer Socket Listener Thread\n");
return 0;
}
void wf_peer_read_settings(freerdp_peer* client)
{
if (!wf_settings_read_string_ascii(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), _T("CertificateFile"), &(client->settings->CertificateFile)))
client->settings->CertificateFile = _strdup("server.crt");
if (!wf_settings_read_string_ascii(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), _T("PrivateKeyFile"), &(client->settings->PrivateKeyFile)))
client->settings->PrivateKeyFile = _strdup("server.key");
}*/
void* mf_peer_main_loop(void* arg)
{
int i;
int fds;
int max_fds;
int rcount;
void* rfds[32];
fd_set rfds_set;
mfPeerContext* context;
freerdp_peer* client = (freerdp_peer*) arg;
memset(rfds, 0, sizeof(rfds));
mf_peer_init(client);
/* Initialize the real server settings here */
client->settings->CertificateFile = _strdup("server.crt");
client->settings->PrivateKeyFile = _strdup("server.key");
client->settings->NlaSecurity = FALSE;
client->settings->RemoteFxCodec = TRUE;
client->settings->SuppressOutput = TRUE;
client->settings->RefreshRect = FALSE;
client->PostConnect = mf_peer_post_connect;
client->Activate = mf_peer_activate;
client->input->SynchronizeEvent = mf_peer_synchronize_event;
client->input->KeyboardEvent = mf_peer_keyboard_event;
client->input->UnicodeKeyboardEvent = mf_peer_unicode_keyboard_event;
client->input->MouseEvent = mf_peer_mouse_event;
client->input->ExtendedMouseEvent = mf_peer_extended_mouse_event;
//client->update->RefreshRect = mf_peer_refresh_rect;
client->update->SuppressOutput = mf_peer_suppress_output;
client->Initialize(client);
context = (mfPeerContext*) 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 (mf_peer_get_fds(client, rfds, &rcount) != TRUE)
{
printf("Failed to get mfreerdp file descriptor\n");
break;
}
#ifdef WITH_SERVER_CHANNELS
WTSVirtualChannelManagerGetFileDescriptor(context->vcm, rfds, &rcount);
#endif
max_fds = 0;
FD_ZERO(&rfds_set);
for (i = 0; i < rcount; i++)
{
fds = (int)(long)(rfds[i]);
if (fds > max_fds)
max_fds = fds;
FD_SET(fds, &rfds_set);
}
if (max_fds == 0)
break;
if (select(max_fds + 1, &rfds_set, NULL, NULL, NULL) == -1)
{
/* these are not really errors */
if (!((errno == EAGAIN) ||
(errno == EWOULDBLOCK) ||
(errno == EINPROGRESS) ||
(errno == EINTR))) /* signal occurred */
{
printf("select failed\n");
break;
}
}
if (client->CheckFileDescriptor(client) != TRUE)
{
printf("Failed to check freerdp file descriptor\n");
break;
}
if ((mf_peer_check_fds(client)) != TRUE)
{
printf("Failed to check mfreerdp file descriptor\n");
break;
}
#ifdef WITH_SERVER_CHANNELS
if (WTSVirtualChannelManagerCheckFileDescriptor(context->vcm) != TRUE)
break;
#endif
}
printf("Client %s disconnected.\n", client->local ? "(local)" : client->hostname);
client->Disconnect(client);
freerdp_peer_context_free(client);
freerdp_peer_free(client);
return NULL;
}

44
server/Mac/mf_peer.h Normal file
View File

@ -0,0 +1,44 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* FreeRDP Mac OS X 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_PEER_H
#define WF_PEER_H
#include "mf_interface.h"
BOOL mf_peer_get_fds(freerdp_peer* client, void** rfds, int* rcount);
BOOL mf_peer_check_fds(freerdp_peer* client);
void mf_peer_rfx_update(freerdp_peer* client);
void mf_peer_context_new(freerdp_peer* client, mfPeerContext* context);
void mf_peer_context_free(freerdp_peer* client, mfPeerContext* context);
void mf_peer_init(freerdp_peer* client);
BOOL mf_peer_post_connect(freerdp_peer* client);
BOOL mf_peer_activate(freerdp_peer* client);
void mf_peer_synchronize_event(rdpInput* input, UINT32 flags);
void mf_peer_accepted(freerdp_listener* instance, freerdp_peer* client);
void* mf_peer_main_loop(void* arg);
#endif /* MF_PEER_H */

View File

@ -3,6 +3,7 @@
* FreeRDP Mac OS X Server
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* 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.
@ -29,260 +30,16 @@
#include <signal.h>
#include <sys/time.h>
#include <CoreGraphics/CGEvent.h>
#include <winpr/crt.h>
#include <freerdp/constants.h>
#include <freerdp/server/rdpsnd.h>
#include "mf_audin.h"
#include "mf_rdpsnd.h"
#include <freerdp/utils/sleep.h>
#include <freerdp/utils/memory.h>
#include "mfreerdp.h"
void mf_peer_context_new(freerdp_peer* client, mfPeerContext* context)
{
context->rfx_context = rfx_context_new();
context->rfx_context->mode = RLGR3;
context->rfx_context->width = client->settings->DesktopWidth;
context->rfx_context->height = client->settings->DesktopHeight;
rfx_context_set_pixel_format(context->rfx_context, RDP_PIXEL_FORMAT_R8G8B8);
context->nsc_context = nsc_context_new();
nsc_context_set_pixel_format(context->nsc_context, RDP_PIXEL_FORMAT_R8G8B8);
context->s = stream_new(0xFFFF);
context->vcm = WTSCreateVirtualChannelManager(client);
}
void mf_peer_context_free(freerdp_peer* client, mfPeerContext* context)
{
if (context)
{
stream_free(context->s);
rfx_context_free(context->rfx_context);
nsc_context_free(context->nsc_context);
if (context->audin)
audin_server_context_free(context->audin);
if (context->rdpsnd)
rdpsnd_server_context_free(context->rdpsnd);
WTSDestroyVirtualChannelManager(context->vcm);
}
}
static void mf_peer_init(freerdp_peer* client)
{
client->context_size = sizeof(mfPeerContext);
client->ContextNew = (psPeerContextNew) mf_peer_context_new;
client->ContextFree = (psPeerContextFree) mf_peer_context_free;
freerdp_peer_context_new(client);
}
BOOL mf_peer_post_connect(freerdp_peer* client)
{
int i;
mfPeerContext* context = (mfPeerContext*) client->context;
printf("Client %s is activated\n", client->hostname);
if (client->settings->AutoLogonEnabled)
{
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->DesktopWidth, client->settings->DesktopHeight, client->settings->ColorDepth);
/* Iterate all channel names requested by the client and activate those supported by the server */
for (i = 0; i < client->settings->ChannelCount; i++)
{
if (client->settings->ChannelDefArray[i].joined)
{
if (strncmp(client->settings->ChannelDefArray[i].Name, "rdpsnd", 6) == 0)
{
mf_peer_rdpsnd_init(context); /* Audio Output */
}
}
}
/* Dynamic Virtual Channels */
mf_peer_audin_init(context); /* Audio Input */
return TRUE;
}
BOOL mf_peer_activate(freerdp_peer* client)
{
mfPeerContext* context = (mfPeerContext*) client->context;
rfx_context_reset(context->rfx_context);
context->activated = TRUE;
return TRUE;
}
void mf_peer_synchronize_event(rdpInput* input, UINT32 flags)
{
printf("Client sent a synchronize event (flags:0x%08X)\n", flags);
}
void mf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
{
printf("Client sent a keyboard event (flags:0x%04X code:0x%04X)\n", flags, code);
}
void mf_peer_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
{
printf("Client sent a unicode keyboard event (flags:0x%04X code:0x%04X)\n", flags, code);
}
void mf_peer_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
{
//printf("Client sent a mouse event (flags:0x%04X pos: %d,%d)\n", flags, x, y);
}
void mf_peer_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
{
//printf("Client sent an extended mouse event (flags:0x%04X pos: %d,%d)\n", flags, x, y);
}
static void mf_peer_refresh_rect(rdpContext* context, BYTE count, RECTANGLE_16* areas)
{
BYTE i;
printf("Client requested to refresh:\n");
for (i = 0; i < count; i++)
{
printf(" (%d, %d) (%d, %d)\n", areas[i].left, areas[i].top, areas[i].right, areas[i].bottom);
}
}
static void mf_peer_suppress_output(rdpContext* context, BYTE allow, RECTANGLE_16* area)
{
if (allow > 0)
{
printf("Client restore output (%d, %d) (%d, %d).\n", area->left, area->top, area->right, area->bottom);
}
else
{
printf("Client minimized and suppress output.\n");
}
}
static void* mf_peer_main_loop(void* arg)
{
int i;
int fds;
int max_fds;
int rcount;
void* rfds[32];
fd_set rfds_set;
mfPeerContext* context;
freerdp_peer* client = (freerdp_peer*) arg;
memset(rfds, 0, sizeof(rfds));
mf_peer_init(client);
/* Initialize the real server settings here */
client->settings->CertificateFile = _strdup("server.crt");
client->settings->PrivateKeyFile = _strdup("server.key");
client->settings->NlaSecurity = FALSE;
client->settings->RemoteFxCodec = TRUE;
client->settings->SuppressOutput = TRUE;
client->settings->RefreshRect = TRUE;
client->PostConnect = mf_peer_post_connect;
client->Activate = mf_peer_activate;
client->input->SynchronizeEvent = mf_peer_synchronize_event;
client->input->KeyboardEvent = mf_peer_keyboard_event;
client->input->UnicodeKeyboardEvent = mf_peer_unicode_keyboard_event;
client->input->MouseEvent = mf_peer_mouse_event;
client->input->ExtendedMouseEvent = mf_peer_extended_mouse_event;
client->update->RefreshRect = mf_peer_refresh_rect;
client->update->SuppressOutput = mf_peer_suppress_output;
client->Initialize(client);
context = (mfPeerContext*) 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;
}
WTSVirtualChannelManagerGetFileDescriptor(context->vcm, rfds, &rcount);
max_fds = 0;
FD_ZERO(&rfds_set);
for (i = 0; i < rcount; i++)
{
fds = (int)(long)(rfds[i]);
if (fds > max_fds)
max_fds = fds;
FD_SET(fds, &rfds_set);
}
if (max_fds == 0)
break;
if (select(max_fds + 1, &rfds_set, NULL, NULL, NULL) == -1)
{
/* these are not really errors */
if (!((errno == EAGAIN) ||
(errno == EWOULDBLOCK) ||
(errno == EINPROGRESS) ||
(errno == EINTR))) /* signal occurred */
{
printf("select failed\n");
break;
}
}
if (client->CheckFileDescriptor(client) != TRUE)
break;
if (WTSVirtualChannelManagerCheckFileDescriptor(context->vcm) != TRUE)
break;
}
printf("Client %s disconnected.\n", client->local ? "(local)" : client->hostname);
client->Disconnect(client);
freerdp_peer_context_free(client);
freerdp_peer_free(client);
return NULL;
}
static void mf_peer_accepted(freerdp_listener* instance, freerdp_peer* client)
{
pthread_t th;
pthread_create(&th, 0, mf_peer_main_loop, client);
pthread_detach(th);
}
#include "mf_peer.h"
static void mf_server_main_loop(freerdp_listener* instance)
{

View File

@ -3,6 +3,7 @@
* FreeRDP Mac OS X Server
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* 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.
@ -23,25 +24,5 @@
#include <freerdp/freerdp.h>
#include <freerdp/listener.h>
#include <freerdp/codec/rfx.h>
#include <freerdp/codec/nsc.h>
#include <freerdp/channels/wtsvc.h>
#include <freerdp/server/audin.h>
#include <freerdp/server/rdpsnd.h>
struct mf_peer_context
{
rdpContext _p;
STREAM* s;
BOOL activated;
UINT32 frame_id;
BOOL audin_open;
RFX_CONTEXT* rfx_context;
NSC_CONTEXT* nsc_context;
WTSVirtualChannelManager* vcm;
audin_server_context* audin;
rdpsnd_server_context* rdpsnd;
};
typedef struct mf_peer_context mfPeerContext;
#endif /* MFREERDP_SERVER_H */

View File

@ -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");

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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 */

View File

@ -24,6 +24,7 @@
#include <winpr/windows.h>
#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));

View File

@ -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;

View File

@ -29,6 +29,7 @@
#include <freerdp/freerdp.h>
#include <freerdp/codec/rfx.h>
#include <freerdp/server/rdpsnd.h>
#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);

View File

@ -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;
}

View File

@ -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);

View File

@ -73,7 +73,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;
@ -81,19 +80,23 @@ 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->DesktopWidth != wfi->servscreen_width) || (settings->DesktopHeight != 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->DesktopWidth, settings->DesktopHeight, wfi->servscreen_width, wfi->servscreen_height);
settings->DesktopWidth = wfi->width;
settings->DesktopHeight = wfi->height;
settings->DesktopWidth = wfi->servscreen_width;
settings->DesktopHeight = wfi->servscreen_height;
settings->ColorDepth = wfi->bitsPerPixel;
client->update->DesktopResize(client->update->context);

View File

@ -46,7 +46,7 @@
IDirectSoundCapture8* cap;
IDirectSoundCaptureBuffer8* capBuf;
DSCBUFFERDESC dscbd;
DWORD capturePos;
DWORD lastPos;
#define BYTESPERSEC 176400
@ -112,7 +112,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);
@ -194,15 +194,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);
@ -214,13 +223,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)
@ -240,9 +251,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();
@ -250,7 +263,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"));
@ -276,21 +289,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"));
@ -300,7 +307,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;
}

View File

@ -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);
}