freerdp: merging with master
This commit is contained in:
commit
7ed7e1c9aa
@ -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")
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
214
server/Mac/mf_event.c
Normal 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
75
server/Mac/mf_event.h
Normal 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
308
server/Mac/mf_info.c
Normal 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
50
server/Mac/mf_info.h
Normal 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 */
|
0
server/Mac/mf_interface.c
Normal file
0
server/Mac/mf_interface.c
Normal file
116
server/Mac/mf_interface.h
Normal file
116
server/Mac/mf_interface.h
Normal 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
|
306
server/Mac/mf_mountain_lion.c
Normal file
306
server/Mac/mf_mountain_lion.c
Normal 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;
|
||||
}
|
||||
|
39
server/Mac/mf_mountain_lion.h
Normal file
39
server/Mac/mf_mountain_lion.h
Normal 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
608
server/Mac/mf_peer.c
Normal 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
44
server/Mac/mf_peer.h
Normal 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 */
|
@ -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)
|
||||
{
|
||||
|
@ -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 */
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user