Merge branch 'master' of github.com:awakecoding/FreeRDP into xkeys

This commit is contained in:
Marc-André Moreau 2014-03-22 13:31:12 -04:00
commit e534ecb4a6
36 changed files with 1914 additions and 1805 deletions

View File

@ -115,9 +115,7 @@ static int rdpsnd_alsa_set_hw_params(rdpsndAlsaPlugin* alsa)
status = snd_pcm_hw_params_set_buffer_size_near(alsa->pcm_handle, hw_params, &alsa->buffer_size); status = snd_pcm_hw_params_set_buffer_size_near(alsa->pcm_handle, hw_params, &alsa->buffer_size);
SND_PCM_CHECK("snd_pcm_hw_params_set_buffer_size_near", status); SND_PCM_CHECK("snd_pcm_hw_params_set_buffer_size_near", status);
/* Get period size */ alsa->period_size = alsa->buffer_size / 2;
status = snd_pcm_hw_params_get_period_size_min(hw_params, &alsa->period_size, NULL);
SND_PCM_CHECK("snd_pcm_hw_params_get_period_size_min", status);
/* Set period size */ /* Set period size */
status = snd_pcm_hw_params_set_period_size_near(alsa->pcm_handle, hw_params, &alsa->period_size, NULL); status = snd_pcm_hw_params_set_period_size_near(alsa->pcm_handle, hw_params, &alsa->period_size, NULL);
@ -191,12 +189,12 @@ static int rdpsnd_alsa_set_params(rdpsndAlsaPlugin* alsa)
* It is also possible for the buffer size to not be an integer multiple of the period size. * It is also possible for the buffer size to not be an integer multiple of the period size.
*/ */
int interrupts_per_sec_near = 20;
int bytes_per_sec = alsa->actual_rate * alsa->bytes_per_channel * alsa->actual_channels;
snd_pcm_drop(alsa->pcm_handle); snd_pcm_drop(alsa->pcm_handle);
if (alsa->latency < 0) alsa->buffer_size = bytes_per_sec / (interrupts_per_sec_near / 2);
alsa->latency = 400;
alsa->buffer_size = alsa->latency * (alsa->actual_rate / 1000);
if (rdpsnd_alsa_set_hw_params(alsa) < 0) if (rdpsnd_alsa_set_hw_params(alsa) < 0)
return -1; return -1;
@ -225,11 +223,6 @@ static void rdpsnd_alsa_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* for
case WAVE_FORMAT_PCM: case WAVE_FORMAT_PCM:
switch (format->wBitsPerSample) switch (format->wBitsPerSample)
{ {
case 4:
alsa->format = SND_PCM_FORMAT_S16_LE;
alsa->bytes_per_channel = 2;
break;
case 8: case 8:
alsa->format = SND_PCM_FORMAT_S8; alsa->format = SND_PCM_FORMAT_S8;
alsa->bytes_per_channel = 1; alsa->bytes_per_channel = 1;

View File

@ -275,14 +275,14 @@ void rdpsnd_recv_server_audio_formats_pdu(rdpsndPlugin* rdpsnd, wStream* s)
UINT16 wVersion; UINT16 wVersion;
AUDIO_FORMAT* format; AUDIO_FORMAT* format;
UINT16 wNumberOfFormats; UINT16 wNumberOfFormats;
UINT32 dwVolume;
rdpsnd_free_audio_formats(rdpsnd->ServerFormats, rdpsnd->NumberOfServerFormats); rdpsnd_free_audio_formats(rdpsnd->ServerFormats, rdpsnd->NumberOfServerFormats);
rdpsnd->NumberOfServerFormats = 0; rdpsnd->NumberOfServerFormats = 0;
rdpsnd->ServerFormats = NULL; rdpsnd->ServerFormats = NULL;
/* http://msdn.microsoft.com/en-us/library/cc240956.aspx */
Stream_Seek_UINT32(s); /* dwFlags */ Stream_Seek_UINT32(s); /* dwFlags */
Stream_Read_UINT32(s, dwVolume); /* dwVolume */ Stream_Seek_UINT32(s); /* dwVolume */
Stream_Seek_UINT32(s); /* dwPitch */ Stream_Seek_UINT32(s); /* dwPitch */
Stream_Seek_UINT16(s); /* wDGramPort */ Stream_Seek_UINT16(s); /* wDGramPort */
Stream_Read_UINT16(s, wNumberOfFormats); Stream_Read_UINT16(s, wNumberOfFormats);
@ -324,9 +324,6 @@ void rdpsnd_recv_server_audio_formats_pdu(rdpsndPlugin* rdpsnd, wStream* s)
if (wVersion >= 6) if (wVersion >= 6)
rdpsnd_send_quality_mode_pdu(rdpsnd); rdpsnd_send_quality_mode_pdu(rdpsnd);
if (rdpsnd->device)
IFCALL(rdpsnd->device->SetVolume, rdpsnd->device, dwVolume);
} }
void rdpsnd_send_training_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, UINT16 wPackSize) void rdpsnd_send_training_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, UINT16 wPackSize)
@ -1094,8 +1091,6 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
rdpsnd->log = WLog_Get("com.freerdp.channels.rdpsnd.client"); rdpsnd->log = WLog_Get("com.freerdp.channels.rdpsnd.client");
WLog_SetLogLevel(rdpsnd->log, WLOG_TRACE);
rdpsnd->channelEntryPoints.pVirtualChannelInit(&rdpsnd->InitHandle, rdpsnd->channelEntryPoints.pVirtualChannelInit(&rdpsnd->InitHandle,
&rdpsnd->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, rdpsnd_virtual_channel_init_event); &rdpsnd->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, rdpsnd_virtual_channel_init_event);

View File

@ -41,6 +41,15 @@ static HWND g_focus_hWnd;
BOOL wf_scale_blt(wfContext* wfc, HDC hdc, int x, int y, int w, int h, HDC hdcSrc, int x1, int y1, DWORD rop); BOOL wf_scale_blt(wfContext* wfc, HDC hdc, int x, int y, int w, int h, HDC hdcSrc, int x1, int y1, DWORD rop);
void wf_scale_mouse_event(wfContext* wfc, rdpInput* input, UINT16 flags, UINT16 x, UINT16 y); void wf_scale_mouse_event(wfContext* wfc, rdpInput* input, UINT16 flags, UINT16 x, UINT16 y);
static BOOL g_flipping_in;
static BOOL g_flipping_out;
static BOOL alt_ctrl_down()
{
return ((GetAsyncKeyState(VK_CONTROL) & 0x8000) ||
(GetAsyncKeyState(VK_MENU) & 0x8000));
}
LRESULT CALLBACK wf_ll_kbd_proc(int nCode, WPARAM wParam, LPARAM lParam) LRESULT CALLBACK wf_ll_kbd_proc(int nCode, WPARAM wParam, LPARAM lParam)
{ {
wfContext* wfc; wfContext* wfc;
@ -50,6 +59,13 @@ LRESULT CALLBACK wf_ll_kbd_proc(int nCode, WPARAM wParam, LPARAM lParam)
DEBUG_KBD("Low-level keyboard hook, hWnd %X nCode %X wParam %X", g_focus_hWnd, nCode, wParam); DEBUG_KBD("Low-level keyboard hook, hWnd %X nCode %X wParam %X", g_focus_hWnd, nCode, wParam);
if (g_flipping_in)
{
if (!alt_ctrl_down())
g_flipping_in = FALSE;
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
if (g_focus_hWnd && (nCode == HC_ACTION)) if (g_focus_hWnd && (nCode == HC_ACTION))
{ {
switch (wParam) switch (wParam)
@ -124,6 +140,15 @@ LRESULT CALLBACK wf_ll_kbd_proc(int nCode, WPARAM wParam, LPARAM lParam)
} }
} }
if (g_flipping_out)
{
if (!alt_ctrl_down())
{
g_flipping_out = FALSE;
g_focus_hWnd = NULL;
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam); return CallNextHookEx(NULL, nCode, wParam, lParam);
} }
@ -505,6 +530,8 @@ LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam
case WM_SETFOCUS: case WM_SETFOCUS:
DEBUG_KBD("getting focus %X", hWnd); DEBUG_KBD("getting focus %X", hWnd);
if (alt_ctrl_down())
g_flipping_in = TRUE;
g_focus_hWnd = hWnd; g_focus_hWnd = hWnd;
break; break;
@ -512,7 +539,10 @@ LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam
if (g_focus_hWnd == hWnd && wfc && !wfc->fullscreen) if (g_focus_hWnd == hWnd && wfc && !wfc->fullscreen)
{ {
DEBUG_KBD("loosing focus %X", hWnd); DEBUG_KBD("loosing focus %X", hWnd);
g_focus_hWnd = NULL; if (alt_ctrl_down())
g_flipping_out = TRUE;
else
g_focus_hWnd = NULL;
} }
break; break;
@ -521,11 +551,16 @@ LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam
int activate = (int)(short) LOWORD(wParam); int activate = (int)(short) LOWORD(wParam);
if (activate != WA_INACTIVE) if (activate != WA_INACTIVE)
{ {
if (alt_ctrl_down())
g_flipping_in = TRUE;
g_focus_hWnd = hWnd; g_focus_hWnd = hWnd;
} }
else else
{ {
g_focus_hWnd = NULL; if (alt_ctrl_down())
g_flipping_out = TRUE;
else
g_focus_hWnd = NULL;
} }
} }

View File

@ -1,45 +0,0 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Implements Microsoft Point to Point Compression (MPPC) protocol
*
* Copyright 2011 Laxmikant Rashinkar <LK.Rashinkar@gmail.com>
* Copyright Jiten Pathy
*
* 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 FREERDP_CODEC_MPPC_DECODER_H
#define FREERDP_CODEC_MPPC_DECODER_H
#include <freerdp/api.h>
#include <freerdp/types.h>
#include <freerdp/codec/mppc.h>
#define RDP6_HISTORY_BUF_SIZE 65536
#define RDP6_OFFSET_CACHE_SIZE 8
struct rdp_mppc_dec
{
BYTE* history_buf;
UINT16* offset_cache;
BYTE* history_buf_end;
BYTE* history_ptr;
};
FREERDP_API int decompress_rdp_6(struct rdp_mppc_dec* dec, BYTE* cbuf, int len, int ctype, UINT32* roff, UINT32* rlen);
FREERDP_API struct rdp_mppc_dec* mppc_dec_new(void);
FREERDP_API void mppc_dec_free(struct rdp_mppc_dec* dec);
#endif /* FREERDP_CODEC_MPPC_DECODER_H */

View File

@ -1,51 +0,0 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Implements Microsoft Point to Point Compression (MPPC) protocol
*
* Copyright 2012 Laxmikant Rashinkar <LK.Rashinkar@gmail.com>
* Copyright 2012 Jay Sorg <jay.sorg@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 FREERDP_CODEC_MPPC_ENCODER_H
#define FREERDP_CODEC_MPPC_ENCODER_H
#include <freerdp/api.h>
#include <freerdp/types.h>
#define PROTO_RDP_40 1
#define PROTO_RDP_50 2
struct rdp_mppc_enc
{
int protocol_type; /* PROTO_RDP_40, PROTO_RDP_50 etc */
char* historyBuffer; /* contains uncompressed data */
char* outputBuffer; /* contains compressed data */
char* outputBufferPlus;
int historyOffset; /* next free slot in historyBuffer */
int buf_len; /* length of historyBuffer, protocol dependant */
int bytes_in_opb; /* compressed bytes available in outputBuffer */
int flags; /* PACKET_COMPRESSED, PACKET_AT_FRONT, PACKET_FLUSHED etc */
int flagsHold;
int first_pkt; /* this is the first pkt passing through enc */
UINT16* hash_table;
};
FREERDP_API BOOL compress_rdp(struct rdp_mppc_enc* enc, BYTE* srcData, int len);
FREERDP_API BOOL compress_rdp_4(struct rdp_mppc_enc* enc, BYTE* srcData, int len);
FREERDP_API BOOL compress_rdp_5(struct rdp_mppc_enc* enc, BYTE* srcData, int len);
FREERDP_API struct rdp_mppc_enc* mppc_enc_new(int protocol_type);
FREERDP_API void mppc_enc_free(struct rdp_mppc_enc* enc);
#endif /* FREERDP_CODEC_MPPC_ENCODER_H */

View File

@ -0,0 +1,59 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* NCrush (RDP6) Bulk Data Compression
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FREERDP_CODEC_NCRUSH_H
#define FREERDP_CODEC_NCRUSH_H
#include <freerdp/api.h>
#include <freerdp/types.h>
#include <freerdp/codec/mppc.h>
#include <winpr/bitstream.h>
struct _NCRUSH_CONTEXT
{
BOOL Compressor;
BYTE* HistoryPtr;
UINT32 HistoryOffset;
UINT32 HistoryEndOffset;
BYTE HistoryBuffer[65536];
UINT32 HistoryBufferFence;
UINT32 OffsetCache[4];
};
typedef struct _NCRUSH_CONTEXT NCRUSH_CONTEXT;
#ifdef __cplusplus
extern "C" {
#endif
FREERDP_API int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstData, UINT32* pDstSize, UINT32* pFlags);
FREERDP_API int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags);
FREERDP_API void ncrush_context_reset(NCRUSH_CONTEXT* ncrush);
FREERDP_API NCRUSH_CONTEXT* ncrush_context_new(BOOL Compressor);
FREERDP_API void ncrush_context_free(NCRUSH_CONTEXT* ncrush);
#ifdef __cplusplus
}
#endif
#endif /* FREERDP_CODEC_NCRUSH_H */

View File

@ -176,6 +176,59 @@ FREERDP_API extern int connectErrorCode;
#define INSUFFICIENTPRIVILEGESERROR ERRORSTART + 10 #define INSUFFICIENTPRIVILEGESERROR ERRORSTART + 10
#define CANCELEDBYUSER ERRORSTART + 11 #define CANCELEDBYUSER ERRORSTART + 11
/**
* FreeRDP Context Error Codes
*/
#define MAKE_FREERDP_ERROR(_class, _type) \
(((FREERDP_ERROR_ ## _class ## _CLASS) << 16) | (_type))
#define GET_FREERDP_ERROR_CLASS(_errorCode) \
((_errorCode >> 16) & 0xFFFF)
#define GET_FREERDP_ERROR_TYPE(_errorCode) \
(_errorCode & 0xFFFF)
#define GET_FREERDP_ERROR_SUBCODE
#define FREERDP_ERROR_BASE 0
#define FREERDP_ERROR_SUCCESS ERRINFO_SUCCESS
#define FREERDP_ERROR_NONE ERRINFO_NONE
/* Error Info Codes */
#define FREERDP_ERROR_ERRINFO_CLASS (FREERDP_ERROR_BASE + 1)
#define FREERDP_ERROR_RPC_INITIATED_DISCONNECT MAKE_FREERDP_ERROR(ERRINFO, ERRINFO_RPC_INITIATED_DISCONNECT)
#define FREERDP_ERROR_RPC_INITIATED_LOGOFF MAKE_FREERDP_ERROR(ERRINFO, ERRINFO_RPC_INITIATED_LOGOFF)
#define FREERDP_ERROR_IDLE_TIMEOUT MAKE_FREERDP_ERROR(ERRINFO, ERRINFO_IDLE_TIMEOUT)
#define FREERDP_ERROR_LOGON_TIMEOUT MAKE_FREERDP_ERROR(ERRINFO, ERRINFO_LOGON_TIMEOUT)
#define FREERDP_ERROR_DISCONNECTED_BY_OTHER_CONNECTION MAKE_FREERDP_ERROR(ERRINFO, ERRINFO_DISCONNECTED_BY_OTHER_CONNECTION)
#define FREERDP_ERROR_OUT_OF_MEMORY MAKE_FREERDP_ERROR(ERRINFO, ERRINFO_OUT_OF_MEMORY)
#define FREERDP_ERROR_SERVER_DENIED_CONNECTION MAKE_FREERDP_ERROR(ERRINFO, ERRINFO_SERVER_DENIED_CONNECTION)
#define FREERDP_ERROR_SERVER_INSUFFICIENT_PRIVILEGES MAKE_FREERDP_ERROR(ERRINFO, ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES)
#define FREERDP_ERROR_SERVER_FRESH_CREDENTIALS_REQUIRED MAKE_FREERDP_ERROR(ERRINFO, ERRINFO_SERVER_FRESH_CREDENTIALS_REQUIRED)
#define FREERDP_ERROR_RPC_INITIATED_DISCONNECT_BY_USER MAKE_FREERDP_ERROR(ERRINFO, ERRINFO_RPC_INITIATED_DISCONNECT_BY_USER)
#define FREERDP_ERROR_LOGOFF_BY_USER MAKE_FREERDP_ERROR(ERRINFO, ERRINFO_LOGOFF_BY_USER)
/* Connection Error Codes */
#define FREERDP_ERROR_CONNECT_CLASS (FREERDP_ERROR_BASE + 2)
#define FREERDP_ERROR_PRE_CONNECT_FAILED MAKE_FREERDP_ERROR(CONNECT, 1)
#define FREERDP_ERROR_CONNECT_UNDEFINED MAKE_FREERDP_ERROR(CONNECT, 2)
#define FREERDP_ERROR_POST_CONNECT_FAILED MAKE_FREERDP_ERROR(CONNECT, 3)
#define FREERDP_ERROR_DNS_ERROR MAKE_FREERDP_ERROR(CONNECT, 4)
#define FREERDP_ERROR_DNS_NAME_NOT_FOUND MAKE_FREERDP_ERROR(CONNECT, 5)
#define FREERDP_ERROR_CONNECT_FAILED MAKE_FREERDP_ERROR(CONNECT, 6)
#define FREERDP_ERROR_MCS_CONNECT_INITIAL_ERROR MAKE_FREERDP_ERROR(CONNECT, 7)
#define FREERDP_ERROR_TLS_CONNECT_FAILED MAKE_FREERDP_ERROR(CONNECT, 8)
#define FREERDP_ERROR_AUTHENTICATION_FAILED MAKE_FREERDP_ERROR(CONNECT, 9)
#define FREERDP_ERROR_INSUFFICIENT_PRIVILEGES MAKE_FREERDP_ERROR(CONNECT, 10)
#define FREERDP_ERROR_CONNECT_CANCELLED MAKE_FREERDP_ERROR(CONNECT, 11)
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -85,7 +85,9 @@ struct rdp_context
This field is used only on the server side. */ This field is used only on the server side. */
ALIGN64 BOOL ServerMode; /**< (offset 2) true when context is in server mode */ ALIGN64 BOOL ServerMode; /**< (offset 2) true when context is in server mode */
UINT64 paddingA[16 - 3]; /* 3 */ ALIGN64 UINT32 LastError; /* 3 */
UINT64 paddingA[16 - 4]; /* 4 */
ALIGN64 int argc; /**< (offset 16) ALIGN64 int argc; /**< (offset 16)
Number of arguments given to the program at launch time. Number of arguments given to the program at launch time.
@ -247,6 +249,9 @@ FREERDP_API void freerdp_free(freerdp* instance);
FREERDP_API BOOL freerdp_focus_required(freerdp* instance); FREERDP_API BOOL freerdp_focus_required(freerdp* instance);
FREERDP_API UINT32 freerdp_get_last_error(rdpContext* context);
FREERDP_API void freerdp_set_last_error(rdpContext* context, UINT32 lastError);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -47,9 +47,8 @@ set(${MODULE_PREFIX}_SRCS
nsc_encode.c nsc_encode.c
nsc_encode.h nsc_encode.h
nsc_types.h nsc_types.h
ncrush.c
mppc.c mppc.c
mppc_dec.c
mppc_enc.c
jpeg.c) jpeg.c)
set(${MODULE_PREFIX}_SSE2_SRCS set(${MODULE_PREFIX}_SSE2_SRCS

View File

@ -26,9 +26,6 @@
#include <winpr/stream.h> #include <winpr/stream.h>
#include <winpr/bitstream.h> #include <winpr/bitstream.h>
#include <freerdp/codec/mppc_enc.h>
#include <freerdp/codec/mppc_dec.h>
#include <freerdp/codec/mppc.h> #include <freerdp/codec/mppc.h>
#define MPPC_MATCH_INDEX(_sym1, _sym2, _sym3) \ #define MPPC_MATCH_INDEX(_sym1, _sym2, _sym3) \
@ -113,13 +110,8 @@ int mppc_decompress(MPPC_CONTEXT* mppc, BYTE* pSrcData, UINT32 SrcSize, BYTE** p
if (!(flags & PACKET_COMPRESSED)) if (!(flags & PACKET_COMPRESSED))
{ {
CopyMemory(HistoryPtr, pSrcData, SrcSize);
HistoryPtr += SrcSize;
HistoryOffset += SrcSize;
mppc->HistoryPtr = HistoryPtr;
mppc->HistoryOffset = HistoryOffset;
*ppDstData = HistoryPtr;
*pDstSize = SrcSize; *pDstSize = SrcSize;
*ppDstData = pSrcData;
return 1; return 1;
} }
@ -535,6 +527,7 @@ int mppc_compress(MPPC_CONTEXT* mppc, BYTE* pSrcData, UINT32 SrcSize, BYTE* pDst
*pFlags |= PACKET_FLUSHED; *pFlags |= PACKET_FLUSHED;
ZeroMemory(HistoryBuffer, HistoryBufferSize); ZeroMemory(HistoryBuffer, HistoryBufferSize);
ZeroMemory(mppc->MatchBuffer, sizeof(mppc->MatchBuffer)); ZeroMemory(mppc->MatchBuffer, sizeof(mppc->MatchBuffer));
*pDstSize = SrcSize;
return 1; return 1;
} }
@ -585,6 +578,7 @@ int mppc_compress(MPPC_CONTEXT* mppc, BYTE* pSrcData, UINT32 SrcSize, BYTE* pDst
*pFlags = PACKET_FLUSHED; *pFlags = PACKET_FLUSHED;
ZeroMemory(HistoryBuffer, HistoryBufferSize); ZeroMemory(HistoryBuffer, HistoryBufferSize);
ZeroMemory(mppc->MatchBuffer, sizeof(mppc->MatchBuffer)); ZeroMemory(mppc->MatchBuffer, sizeof(mppc->MatchBuffer));
*pDstSize = SrcSize;
return 1; return 1;
} }
@ -740,6 +734,7 @@ int mppc_compress(MPPC_CONTEXT* mppc, BYTE* pSrcData, UINT32 SrcSize, BYTE* pDst
*pFlags |= PACKET_FLUSHED; *pFlags |= PACKET_FLUSHED;
ZeroMemory(HistoryBuffer, HistoryBufferSize); ZeroMemory(HistoryBuffer, HistoryBufferSize);
ZeroMemory(mppc->MatchBuffer, sizeof(mppc->MatchBuffer)); ZeroMemory(mppc->MatchBuffer, sizeof(mppc->MatchBuffer));
*pDstSize = SrcSize;
return 1; return 1;
} }

View File

@ -1,530 +0,0 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Implements Microsoft Point to Point Compression (MPPC) protocol
*
* Copyright 2011 Laxmikant Rashinkar <LK.Rashinkar@gmail.com>
* Copyright 2012 Jiten Pathy
*
* 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 <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
#include <freerdp/codec/mppc_dec.h>
static BYTE HuffLenLEC[] = {
0x6, 0x6, 0x6, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x9, 0x8, 0x9, 0x9, 0x9, 0x9, 0x8, 0x8, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x8, 0x9, 0x9, 0xa, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0xa, 0x9, 0xa, 0xa, 0xa, 0x9, 0x9, 0xa, 0x9, 0xa, 0x9, 0xa, 0x9, 0x9, 0x9, 0xa, 0xa, 0x9, 0xa, 0x9, 0x9, 0x8, 0x9, 0x9, 0x9, 0x9, 0xa, 0xa, 0xa, 0x9, 0x9, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0x9, 0x9, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0x9, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0x8, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0x9, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0x9, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0x9, 0x7, 0x9, 0x9, 0xa, 0x9, 0xa, 0xa, 0xa, 0x9, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0x9, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xd, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xb, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0x9, 0xa, 0xa, 0xa, 0xa, 0xa, 0x9, 0xa, 0xa, 0xa, 0xa, 0xa, 0x9, 0xa, 0xa, 0xa, 0x9, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0x9, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0x9, 0xa, 0x8, 0x9, 0x9, 0xa, 0x9, 0xa, 0xa, 0xa, 0x9, 0xa, 0xa, 0xa, 0x9, 0x9, 0x8, 0x7, 0xd, 0xd, 0x7, 0x7, 0xa, 0x7, 0x7, 0x6, 0x6, 0x6, 0x6, 0x5, 0x6, 0x6, 0x6, 0x5, 0x6, 0x5, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x8, 0x5, 0x6, 0x7, 0x7 };
static UINT16 HuffIndexLEC[512] = {
0x007b, 0xff1f, 0xff0d, 0xfe27, 0xfe00, 0xff05, 0xff17, 0xfe68, 0x00c5, 0xfe07, 0xff13, 0xfec0, 0xff08, 0xfe18, 0xff1b, 0xfeb3, 0xfe03, 0x00a2, 0xfe42, 0xff10, 0xfe0b, 0xfe02, 0xfe91, 0xff19, 0xfe80, 0x00e9, 0xfe3a, 0xff15, 0xfe12, 0x0057, 0xfed7, 0xff1d, 0xff0e, 0xfe35, 0xfe69, 0xff22, 0xff18, 0xfe7a, 0xfe01, 0xff23, 0xff14, 0xfef4, 0xfeb4, 0xfe09, 0xff1c, 0xfec4, 0xff09, 0xfe60, 0xfe70, 0xff12, 0xfe05, 0xfe92, 0xfea1, 0xff1a, 0xfe0f, 0xff07, 0xfe56, 0xff16, 0xff02, 0xfed8, 0xfee8, 0xff1e, 0xfe1d, 0x003b, 0xffff, 0xff06, 0xffff, 0xfe71, 0xfe89, 0xffff, 0xffff, 0xfe2c, 0xfe2b, 0xfe20, 0xffff, 0xfebb, 0xfecf, 0xfe08, 0xffff, 0xfee0, 0xfe0d, 0xffff, 0xfe99, 0xffff, 0xfe04, 0xfeaa, 0xfe49, 0xffff, 0xfe17, 0xfe61, 0xfedf, 0xffff, 0xfeff, 0xfef6, 0xfe4c, 0xffff, 0xffff, 0xfe87, 0xffff, 0xff24, 0xffff, 0xfe3c, 0xfe72, 0xffff, 0xffff, 0xfece, 0xffff, 0xfefe, 0xffff, 0xfe23, 0xfebc, 0xfe0a, 0xfea9, 0xffff, 0xfe11, 0xffff, 0xfe82, 0xffff, 0xfe06, 0xfe9a, 0xfef5, 0xffff, 0xfe22, 0xfe4d, 0xfe5f, 0xffff, 0xff03, 0xfee1, 0xffff, 0xfeca, 0xfecc, 0xffff, 0xfe19, 0xffff, 0xfeb7, 0xffff, 0xffff, 0xfe83, 0xfe29, 0xffff, 0xffff, 0xffff, 0xfe6c, 0xffff, 0xfeed, 0xffff, 0xffff, 0xfe46, 0xfe5c, 0xfe15, 0xffff, 0xfedb, 0xfea6, 0xffff, 0xffff, 0xfe44, 0xffff, 0xfe0c, 0xffff, 0xfe95, 0xfefc, 0xffff, 0xffff, 0xfeb8, 0x16c9, 0xffff, 0xfef0, 0xffff, 0xfe38, 0xffff, 0xffff, 0xfe6d, 0xfe7e, 0xffff, 0xffff, 0xffff, 0xffff, 0xfe5b, 0xfedc, 0xffff, 0xffff, 0xfeec, 0xfe47, 0xfe1f, 0xffff, 0xfe7f, 0xfe96, 0xffff, 0xffff, 0xfea5, 0xffff, 0xfe10, 0xfe40, 0xfe32, 0xfebf, 0xffff, 0xffff, 0xfed4, 0xfef1, 0xffff, 0xffff, 0xffff, 0xfe75, 0xffff, 0xffff, 0xfe8d, 0xfe31, 0xffff, 0xfe65, 0xfe1b, 0xffff, 0xfee4, 0xfefb, 0xffff, 0xffff, 0xfe52, 0xffff, 0xfe0e, 0xffff, 0xfe9d, 0xfeaf, 0xffff, 0xffff, 0xfe51, 0xfed3, 0xffff, 0xff20, 0xffff, 0xfe2f, 0xffff, 0xffff, 0xfec1, 0xfe8c, 0xffff, 0xffff, 0xffff, 0xfe3f, 0xffff, 0xffff, 0xfe76, 0xffff, 0xfefa, 0xfe53, 0xfe25, 0xffff, 0xfe64, 0xfee5, 0xffff, 0xffff, 0xfeae, 0xffff, 0xfe13, 0xffff, 0xfe88, 0xfe9e, 0xffff, 0xfe43, 0xffff, 0xffff, 0xfea4, 0xfe93, 0xffff, 0xffff, 0xffff, 0xfe3d, 0xffff, 0xffff, 0xfeeb, 0xfed9, 0xffff, 0xfe14, 0xfe5a, 0xffff, 0xfe28, 0xfe7d, 0xffff, 0xffff, 0xfe6a, 0xffff, 0xffff, 0xff01, 0xfec6, 0xfec8, 0xffff, 0xffff, 0xfeb5, 0xffff, 0xffff, 0xffff, 0xfe94, 0xfe78, 0xffff, 0xffff, 0xffff, 0xfea3, 0xffff, 0xffff, 0xfeda, 0xfe58, 0xffff, 0xfe1e, 0xfe45, 0xfeea, 0xffff, 0xfe6b, 0xffff, 0xffff, 0xfe37, 0xffff, 0xffff, 0xffff, 0xfe7c, 0xfeb6, 0xffff, 0xffff, 0xfef8, 0xffff, 0xffff, 0xffff, 0xfec7, 0xfe9b, 0xffff, 0xffff, 0xffff, 0xfe50, 0xffff, 0xffff, 0xfead, 0xfee2, 0xffff, 0xfe1a, 0xfe63, 0xfe4e, 0xffff, 0xffff, 0xfef9, 0xffff, 0xfe73, 0xffff, 0xffff, 0xffff, 0xfe30, 0xfe8b, 0xffff, 0xffff, 0xfebd, 0xfe2e, 0x0100, 0xffff, 0xfeee, 0xfed2, 0xffff, 0xffff, 0xffff, 0xfeac, 0xffff, 0xffff, 0xfe9c, 0xfe84, 0xffff, 0xfe24, 0xfe4f, 0xfef7, 0xffff, 0xffff, 0xfee3, 0xfe62, 0xffff, 0xffff, 0xffff, 0xffff, 0xfe8a, 0xfe74, 0xffff, 0xffff, 0xfe3e, 0xffff, 0xffff, 0xffff, 0xfed1, 0xfebe, 0xffff, 0xffff, 0xfe2d, 0xffff, 0xfe4a, 0xfef3, 0xffff, 0xffff, 0xfedd, 0xfe5e, 0xfe16, 0xffff, 0xfe48, 0xfea8, 0xffff, 0xfeab, 0xfe97, 0xffff, 0xffff, 0xfed0, 0xffff, 0xffff, 0xfecd, 0xfeb9, 0xffff, 0xffff, 0xffff, 0xfe2a, 0xffff, 0xffff, 0xfe86, 0xfe6e, 0xffff, 0xffff, 0xffff, 0xfede, 0xffff, 0xffff, 0xfe5d, 0xfe4b, 0xfe21, 0xffff, 0xfeef, 0xfe98, 0xffff, 0xffff, 0xfe81, 0xffff, 0xffff, 0xffff, 0xfea7, 0xffff, 0xfeba, 0xfefd, 0xffff, 0xffff, 0xffff, 0xfecb, 0xffff, 0xffff, 0xfe6f, 0xfe39, 0xffff, 0xffff, 0xffff, 0xfe85, 0xffff, 0x010c, 0xfee6, 0xfe67, 0xfe1c, 0xffff, 0xfe54, 0xfeb2, 0xffff, 0xffff, 0xfe9f, 0xffff, 0xffff, 0xffff, 0xfe59, 0xfeb1, 0xffff, 0xfec2, 0xffff, 0xffff, 0xfe36, 0xfef2, 0xffff, 0xffff, 0xfed6, 0xfe77, 0xffff, 0xffff, 0xffff, 0xfe33, 0xffff, 0xffff, 0xfe8f, 0xfe55, 0xfe26, 0x010a, 0xff04, 0xfee7, 0xffff, 0x0121, 0xfe66, 0xffff, 0xffff, 0xffff, 0xfeb0, 0xfea0, 0xffff, 0x010f, 0xfe90, 0xffff, 0xffff, 0xfed5, 0xffff, 0xffff, 0xfec3, 0xfe34, 0xffff, 0xffff, 0xffff, 0xfe8e, 0xffff, 0x0111, 0xfe79, 0xfe41, 0x010b };
static UINT16 LECHTab[] = {511, 0, 508, 448, 494, 347, 486, 482};
static BYTE HuffLenLOM[] = {
0x4, 0x2, 0x3, 0x4, 0x3, 0x4, 0x4, 0x5, 0x4, 0x5, 0x5, 0x6, 0x6, 0x7, 0x7, 0x8, 0x7, 0x8, 0x8, 0x9, 0x9, 0x8, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9 };
static UINT16 HuffIndexLOM[] = {
0xfe1, 0xfe0, 0xfe2, 0xfe8, 0xe, 0xfe5, 0xfe4, 0xfea, 0xff1, 0xfe3, 0x15, 0xfe7, 0xfef, 0x46, 0xff0, 0xfed, 0xfff, 0xff7, 0xffb, 0x19, 0xffd, 0xff4, 0x12c, 0xfeb, 0xffe, 0xff6, 0xffa, 0x89, 0xffc, 0xff3, 0xff8, 0xff2 };
static BYTE LOMHTab[] = {0, 4, 10, 19};
static BYTE CopyOffsetBitsLUT[] = {
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15 };
static UINT32 CopyOffsetBaseLUT[] = {
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 32769, 49153, 65537 };
static BYTE LOMBitsLUT[] = {
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 6, 6, 8, 8, 14, 14 };
static UINT16 LOMBaseLUT[] = {
2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 22, 26, 30, 34, 42, 50, 58, 66, 82, 98, 114, 130, 194, 258, 514, 2, 2 };
UINT16 LEChash(UINT16 key)
{
return ((key & 0x1ff) ^ (key >> 9) ^ (key >> 4) ^ (key >> 7));
}
UINT16 LOMhash(UINT16 key)
{
return ((key & 0x1f) ^ (key >> 5) ^ (key >> 9));
}
UINT16 miniLEChash(UINT16 key)
{
UINT16 h;
h = ((((key >> 8) ^ (key & 0xff)) >> 2) & 0xf);
if(key >> 9)
h = ~h;
return (h % 12);
}
BYTE miniLOMhash(UINT16 key)
{
BYTE h;
h = (key >> 4) & 0xf;
return ((h ^ (h >> 2) ^ (h >> 3)) & 0x3);
}
UINT16 getLECindex(UINT16 huff)
{
UINT16 h = HuffIndexLEC[LEChash(huff)];
if((h ^ huff) >> 9)
return h & 0x1ff;
else
return HuffIndexLEC[LECHTab[miniLEChash(huff)]];
}
UINT16 getLOMindex(UINT16 huff)
{
UINT16 h = HuffIndexLOM[LOMhash(huff)];
if((h ^ huff) >> 5)
{
return h & 0x1f;
}
else
return HuffIndexLOM[LOMHTab[miniLOMhash(huff)]];
}
UINT32 transposebits(UINT32 x)
{
x = ((x & 0x55555555) << 1) | ((x >> 1) & 0x55555555);
x = ((x & 0x33333333) << 2) | ((x >> 2) & 0x33333333);
x = ((x & 0x0f0f0f0f) << 4) | ((x >> 4) & 0x0f0f0f0f);
if((x >> 8) == 0)
return x;
x = ((x & 0x00ff00ff) << 8) | ((x >> 8) & 0x00ff00ff);
if((x >> 16) == 0)
return x;
x = ((x & 0x0000ffff) << 16) | ((x >> 16) & 0x0000ffff);
return x;
}
#define cache_add(_s, _x) do { \
*((UINT32*)((_s)+2)) <<= 16; \
*((UINT32*)((_s)+2)) |= (*((UINT32*)(_s)) >> 16); \
*((UINT32*)(_s)) = (*((UINT32*)(_s)) << 16) | (_x); } while(0)
#define cache_swap(_s, _i) do { \
UINT16 t = *(_s); \
*(_s) = *((_s) + (_i)); \
*((_s) + (_i)) = t; } while(0)
/**
* decompress RDP 6 data
*
* @param rdp per session information
* @param cbuf compressed data
* @param len length of compressed data
* @param ctype compression flags
* @param roff starting offset of uncompressed data
* @param rlen length of uncompressed data
*
* @return True on success, False on failure
*/
int decompress_rdp_6(struct rdp_mppc_dec* dec, BYTE* cbuf, int len, int ctype, UINT32* roff, UINT32* rlen)
{
BYTE* history_buf; /* uncompressed data goes here */
UINT16* offset_cache; /* Copy Offset cache */
BYTE* history_ptr; /* points to next free slot in bistory_buf */
UINT32 d32; /* we process 4 compressed bytes at a time */
UINT16 copy_offset; /* location to copy data from */
UINT16 lom; /* length of match */
UINT16 LUTIndex; /* LookUp table Index */
BYTE* src_ptr; /* used while copying compressed data */
BYTE* cptr; /* points to next byte in cbuf */
BYTE cur_byte; /* last byte fetched from cbuf */
int bits_left; /* bits left in d32 for processing */
int cur_bits_left; /* bits left in cur_byte for processing */
int tmp, i;
UINT32 i32;
if ((dec == NULL) || (dec->history_buf == NULL))
{
fprintf(stderr, "decompress_rdp_6: null\n");
return FALSE;
}
src_ptr = 0;
cptr = cbuf;
copy_offset = 0;
lom = 0;
bits_left = 0;
cur_bits_left = 0;
d32 = 0;
cur_byte = 0;
*rlen = 0;
/* get start of history buffer */
history_buf = dec->history_buf;
/* get start of offset_cache */
offset_cache = dec->offset_cache;
/* get next free slot in history buffer */
history_ptr = dec->history_ptr;
*roff = history_ptr - history_buf;
if (ctype & PACKET_AT_FRONT)
{
/* slid history_buf and reset history_buf to middle */
memmove(history_buf, (history_buf + (history_ptr - history_buf - 32768)), 32768);
history_ptr = history_buf + 32768;
dec->history_ptr = history_ptr;
*roff = 32768;
}
if (ctype & PACKET_FLUSHED)
{
/* re-init history buffer */
history_ptr = dec->history_buf;
memset(history_buf, 0, RDP6_HISTORY_BUF_SIZE);
memset(offset_cache, 0, RDP6_OFFSET_CACHE_SIZE);
*roff = 0;
}
if ((ctype & PACKET_COMPRESSED) != PACKET_COMPRESSED)
{
/* data in cbuf is not compressed - copy to history buf as is */
memcpy(history_ptr, cbuf, len);
history_ptr += len;
*rlen = history_ptr - dec->history_ptr;
dec->history_ptr = history_ptr;
return TRUE;
}
/* load initial data */
tmp = 0;
while (cptr < cbuf + len)
{
i32 = *cptr++;
d32 |= i32 << tmp;
bits_left += 8;
tmp += 8;
if (tmp >= 32)
{
break;
}
}
d32 = transposebits(d32);
if (cptr < cbuf + len)
{
cur_byte = transposebits(*cptr++);
cur_bits_left = 8;
}
else
{
cur_bits_left = 0;
}
/*
** start uncompressing data in cbuf
*/
while (bits_left >= 8)
{
/* Decode Huffman Code for Literal/EOS/CopyOffset */
copy_offset = 0;
for(i = 0x5; i <= 0xd; i++)
{
if(i == 0xc)
continue;
i32 = transposebits((d32 & (0xffffffff << (32 - i))));
i32 = getLECindex(i32);
if(i == HuffLenLEC[i32])
break;
}
d32 <<= i;
bits_left -= i;
if(i32 < 256)
*history_ptr++ = (BYTE)i32;
else if(i32 > 256 && i32 < 289)
{
LUTIndex = i32 - 257;
tmp = CopyOffsetBitsLUT[LUTIndex];
copy_offset = CopyOffsetBaseLUT[LUTIndex] - 0x1;
if(tmp != 0)
copy_offset += transposebits(d32 & (0xffffffff << (32 - tmp)));
cache_add(offset_cache, copy_offset);
d32 <<= tmp;
bits_left -= tmp;
}
else if( i32 > 288 && i32 < 293)
{
LUTIndex = i32 - 289;
copy_offset = *(offset_cache + LUTIndex);
if(LUTIndex != 0)
cache_swap(offset_cache, LUTIndex);
}
else if(i32 == 256)
break;
/*
** get more bits before we process length of match
*/
/* how may bits do we need to get? */
tmp = 32 - bits_left;
while (tmp)
{
if (cur_bits_left < tmp)
{
/* we have less bits than we need */
i32 = cur_byte >> (8 - cur_bits_left);
d32 |= i32 << ((32 - bits_left) - cur_bits_left);
bits_left += cur_bits_left;
tmp -= cur_bits_left;
if (cptr < cbuf + len)
{
/* more compressed data available */
cur_byte = transposebits(*cptr++);
cur_bits_left = 8;
}
else
{
/* no more compressed data available */
tmp = 0;
cur_bits_left = 0;
}
}
else if (cur_bits_left > tmp)
{
/* we have more bits than we need */
d32 |= cur_byte >> (8 - tmp);
cur_byte <<= tmp;
cur_bits_left -= tmp;
bits_left = 32;
break;
}
else
{
/* we have just the right amount of bits */
d32 |= cur_byte >> (8 - tmp);
bits_left = 32;
if (cptr < cbuf + len)
{
cur_byte = transposebits(*cptr++);
cur_bits_left = 8;
}
else
cur_bits_left = 0;
break;
}
}
if (!copy_offset)
continue;
for(i = 0x2; i <= 0x9; i++)
{
i32 = transposebits((d32 & (0xffffffff << (32 - i))));
i32 = getLOMindex(i32);
if(i == HuffLenLOM[i32])
break;
}
d32 <<= i;
bits_left -= i;
tmp = LOMBitsLUT[i32];
lom = LOMBaseLUT[i32];
if(tmp != 0)
lom += transposebits(d32 & (0xffffffff << (32 - tmp)));
d32 <<= tmp;
bits_left -= tmp;
/* now that we have copy_offset and LoM, process them */
src_ptr = history_ptr - copy_offset;
tmp = (lom > copy_offset) ? copy_offset : lom;
i32 = 0;
if (src_ptr >= dec->history_buf)
{
while(tmp > 0)
{
*history_ptr++ = *src_ptr++;
tmp--;
}
while (lom > copy_offset)
{
i32 = ((i32 >= copy_offset)) ? 0 : i32;
*history_ptr++ = *(src_ptr + i32++);
lom--;
}
}
else
{
src_ptr = dec->history_buf_end - (copy_offset - (history_ptr - dec->history_buf));
src_ptr++;
while (tmp && (src_ptr <= dec->history_buf_end))
{
*history_ptr++ = *src_ptr++;
tmp--;
}
src_ptr = dec->history_buf;
while (tmp > 0)
{
*history_ptr++ = *src_ptr++;
tmp--;
}
while (lom > copy_offset)
{
i32 = ((i32 > copy_offset)) ? 0 : i32;
*history_ptr++ = *(src_ptr + i32++);
lom--;
}
}
/*
** get more bits before we restart the loop
*/
/* how may bits do we need to get? */
assert(bits_left <= 32);
assert(cur_bits_left <= bits_left);
tmp = 32 - bits_left;
while (tmp)
{
if (cur_bits_left < tmp)
{
/* we have less bits than we need */
i32 = cur_byte >> (8 - cur_bits_left);
d32 |= (i32 << ((32 - bits_left) - cur_bits_left)) & 0xFFFFFFFF;
bits_left += cur_bits_left;
tmp -= cur_bits_left;
if (cptr < cbuf + len)
{
/* more compressed data available */
cur_byte = transposebits(*cptr++);
cur_bits_left = 8;
}
else
{
/* no more compressed data available */
tmp = 0;
cur_bits_left = 0;
}
}
else if (cur_bits_left > tmp)
{
/* we have more bits than we need */
d32 |= cur_byte >> (8 - tmp);
cur_byte <<= tmp;
cur_bits_left -= tmp;
bits_left = 32;
break;
}
else
{
/* we have just the right amount of bits */
d32 |= cur_byte >> (8 - tmp);
bits_left = 32;
if (cptr < cbuf + len)
{
cur_byte = transposebits(*cptr++);
cur_bits_left = 8;
}
else
{
cur_bits_left = 0;
}
break;
}
}
}/* end while (bits_left >= 8) */
if(ctype & PACKET_FLUSHED)
*rlen = history_ptr - history_buf;
else
*rlen = history_ptr - dec->history_ptr;
dec->history_ptr = history_ptr;
return TRUE;
}
/**
* allocate space to store history buffer
*
* @param rdp rdp struct that contains rdp_mppc struct
* @return pointer to new struct, or NULL on failure
*/
struct rdp_mppc_dec* mppc_dec_new(void)
{
struct rdp_mppc_dec* ptr;
ptr = (struct rdp_mppc_dec*) malloc(sizeof(struct rdp_mppc_dec));
if (!ptr)
{
fprintf(stderr, "mppc_new(): system out of memory\n");
return NULL;
}
ptr->history_buf = (BYTE*) malloc(RDP6_HISTORY_BUF_SIZE);
ZeroMemory(ptr->history_buf, RDP6_HISTORY_BUF_SIZE);
ptr->offset_cache = (UINT16*) malloc(RDP6_OFFSET_CACHE_SIZE);
ZeroMemory(ptr->offset_cache, RDP6_OFFSET_CACHE_SIZE);
if (!ptr->history_buf)
{
fprintf(stderr, "mppc_new(): system out of memory\n");
free(ptr);
return NULL;
}
ptr->history_ptr = ptr->history_buf;
ptr->history_buf_end = ptr->history_buf + RDP6_HISTORY_BUF_SIZE - 1;
return ptr;
}
/**
* free history buffer
*
* @param rdp rdp struct that contains rdp_mppc struct
*/
void mppc_dec_free(struct rdp_mppc_dec* dec)
{
if (!dec)
{
return;
}
if (dec->history_buf)
{
free(dec->history_buf);
dec->history_buf = NULL;
dec->history_ptr = NULL;
}
if (dec->offset_cache)
{
free(dec->offset_cache);
dec->offset_cache = NULL;
}
free(dec);
}

File diff suppressed because it is too large Load Diff

1420
libfreerdp/codec/ncrush.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -7,6 +7,7 @@ set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
set(${MODULE_PREFIX}_TESTS set(${MODULE_PREFIX}_TESTS
TestFreeRDPRegion.c TestFreeRDPRegion.c
TestFreeRDPCodecMppc.c TestFreeRDPCodecMppc.c
TestFreeRDPCodecNCrush.c
TestFreeRDPCodecPlanar.c TestFreeRDPCodecPlanar.c
TestFreeRDPCodecRemoteFX.c) TestFreeRDPCodecRemoteFX.c)

View File

@ -688,18 +688,18 @@ static BYTE TEST_RDP5_UNCOMPRESSED_DATA[] =
* 00 Trailing Bits * 00 Trailing Bits
*/ */
const BYTE TEST_MPPC_BELLS[] = "for.whom.the.bell.tolls,.the.bell.tolls.for.thee!"; static const BYTE TEST_MPPC_BELLS[] = "for.whom.the.bell.tolls,.the.bell.tolls.for.thee!";
/* Flags: 0x0060 Length: 33 */ /* Flags: 0x0060 Length: 33 */
const BYTE TEST_MPPC_BELLS_RDP4[] = static const BYTE TEST_MPPC_BELLS_RDP4[] =
"\x66\x6f\x72\x2e\x77\x68\x6f\x6d\x2e\x74\x68\x65\x2e\x62\x65\x6c" "\x66\x6f\x72\x2e\x77\x68\x6f\x6d\x2e\x74\x68\x65\x2e\x62\x65\x6c"
"\x6c\x2e\x74\x6f\x6c\x6c\x73\x2c\xf4\x37\x2e\x66\xfa\x1f\x19\x94" "\x6c\x2e\x74\x6f\x6c\x6c\x73\x2c\xf4\x37\x2e\x66\xfa\x1f\x19\x94"
"\x84"; "\x84";
/* Flags: 0x0061 Length: 34 */ /* Flags: 0x0061 Length: 34 */
const BYTE TEST_MPPC_BELLS_RDP5[] = static const BYTE TEST_MPPC_BELLS_RDP5[] =
"\x66\x6f\x72\x2e\x77\x68\x6f\x6d\x2e\x74\x68\x65\x2e\x62\x65\x6c" "\x66\x6f\x72\x2e\x77\x68\x6f\x6d\x2e\x74\x68\x65\x2e\x62\x65\x6c"
"\x6c\x2e\x74\x6f\x6c\x6c\x73\x2c\xfa\x1b\x97\x33\x7e\x87\xe3\x32" "\x6c\x2e\x74\x6f\x6c\x6c\x73\x2c\xfa\x1b\x97\x33\x7e\x87\xe3\x32"
"\x90\x80"; "\x90\x80";

View File

@ -0,0 +1,105 @@
#include <winpr/crt.h>
#include <winpr/print.h>
#include <freerdp/codec/ncrush.h>
static const BYTE TEST_BELLS_DATA[] = "for.whom.the.bell.tolls,.the.bell.tolls.for.thee!";
const BYTE TEST_BELLS_NCRUSH[] =
"\xfb\x1d\x7e\xe4\xda\xc7\x1d\x70\xf8\xa1\x6b\x1f\x7d\xc0\xbe\x6b"
"\xef\xb5\xef\x21\x87\xd0\xc5\xe1\x85\x71\xd4\x10\x16\xe7\xda\xfb"
"\x1d\x7e\xe4\xda\x47\x1f\xb0\xef\xbe\xbd\xff\x2f";
int test_NCrushCompressBells()
{
int status;
UINT32 Flags;
UINT32 SrcSize;
BYTE* pSrcData;
UINT32 DstSize;
UINT32 expectedSize;
BYTE OutputBuffer[65536];
NCRUSH_CONTEXT* ncrush;
ncrush = ncrush_context_new(TRUE);
SrcSize = sizeof(TEST_BELLS_DATA) - 1;
pSrcData = (BYTE*) TEST_BELLS_DATA;
DstSize = sizeof(OutputBuffer);
expectedSize = sizeof(TEST_BELLS_NCRUSH) - 1;
status = ncrush_compress(ncrush, pSrcData, SrcSize, OutputBuffer, &DstSize, &Flags);
printf("Flags: 0x%04X DstSize: %d\n", Flags, DstSize);
if (DstSize != expectedSize)
{
printf("NCrushCompressBells: output size mismatch: Actual: %d, Expected: %d\n", DstSize, expectedSize);
return -1;
}
if (memcmp(OutputBuffer, TEST_BELLS_NCRUSH, DstSize) != 0)
{
printf("NCrushCompressBells: output mismatch\n");
printf("Actual\n");
BitDump(OutputBuffer, DstSize * 8, 0);
printf("Expected\n");
BitDump(TEST_BELLS_NCRUSH, DstSize * 8, 0);
return -1;
}
ncrush_context_free(ncrush);
return 1;
}
int test_NCrushDecompressBells()
{
int status;
UINT32 Flags;
BYTE* pSrcData;
UINT32 SrcSize;
UINT32 DstSize;
UINT32 expectedSize;
BYTE* pDstData = NULL;
NCRUSH_CONTEXT* ncrush;
ncrush = ncrush_context_new(FALSE);
SrcSize = sizeof(TEST_BELLS_NCRUSH) - 1;
pSrcData = (BYTE*) TEST_BELLS_NCRUSH;
Flags = PACKET_COMPRESSED | 2;
expectedSize = sizeof(TEST_BELLS_DATA) - 1;
status = ncrush_decompress(ncrush, pSrcData, SrcSize, &pDstData, &DstSize, Flags);
printf("Flags: 0x%04X DstSize: %d\n", Flags, DstSize);
if (DstSize != expectedSize)
{
printf("NCrushDecompressBells: output size mismatch: Actual: %d, Expected: %d\n", DstSize, expectedSize);
return -1;
}
if (memcmp(pDstData, TEST_BELLS_DATA, DstSize) != 0)
{
printf("NCrushDecompressBells: output mismatch\n");
return -1;
}
ncrush_context_free(ncrush);
return 1;
}
int TestFreeRDPCodecNCrush(int argc, char* argv[])
{
//test_NCrushCompressBells();
test_NCrushDecompressBells();
//BitDump(TEST_BELLS_NCRUSH, (sizeof(TEST_BELLS_NCRUSH) - 1) * 8, 0);
return 0;
}

View File

@ -42,37 +42,42 @@ UINT32 bulk_compression_max_size(rdpBulk* bulk)
int bulk_decompress(rdpBulk* bulk, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags) int bulk_decompress(rdpBulk* bulk, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags)
{ {
int status = -1; int status = -1;
UINT32 roff = 0;
UINT32 rlen = 0;
UINT32 CompressedBytes; UINT32 CompressedBytes;
UINT32 UncompressedBytes; UINT32 UncompressedBytes;
UINT32 type = flags & 0x0F; UINT32 type = flags & 0x0F;
switch (type) if (flags & PACKET_COMPRESSED)
{ {
case PACKET_COMPR_TYPE_8K: switch (type)
mppc_set_compression_level(bulk->mppcRecv, 0); {
status = mppc_decompress(bulk->mppcRecv, pSrcData, SrcSize, ppDstData, pDstSize, flags); case PACKET_COMPR_TYPE_8K:
break; mppc_set_compression_level(bulk->mppcRecv, 0);
status = mppc_decompress(bulk->mppcRecv, pSrcData, SrcSize, ppDstData, pDstSize, flags);
break;
case PACKET_COMPR_TYPE_64K: case PACKET_COMPR_TYPE_64K:
mppc_set_compression_level(bulk->mppcRecv, 1); mppc_set_compression_level(bulk->mppcRecv, 1);
status = mppc_decompress(bulk->mppcRecv, pSrcData, SrcSize, ppDstData, pDstSize, flags); status = mppc_decompress(bulk->mppcRecv, pSrcData, SrcSize, ppDstData, pDstSize, flags);
break; break;
case PACKET_COMPR_TYPE_RDP6: case PACKET_COMPR_TYPE_RDP6:
status = decompress_rdp_6(bulk->mppc_dec, pSrcData, SrcSize, flags, &roff, &rlen); status = ncrush_decompress(bulk->ncrushRecv, pSrcData, SrcSize, ppDstData, pDstSize, flags);
*ppDstData = (bulk->mppc_dec->history_buf + roff); break;
*pDstSize = rlen;
break;
case PACKET_COMPR_TYPE_RDP61: case PACKET_COMPR_TYPE_RDP61:
status = -1; status = -1;
break; break;
case PACKET_COMPR_TYPE_RDP8: case PACKET_COMPR_TYPE_RDP8:
status = -1; status = -1;
break; break;
}
}
else
{
*ppDstData = pSrcData;
*pDstSize = SrcSize;
status = 1;
} }
if (status >= 0) if (status >= 0)
@ -91,16 +96,22 @@ int bulk_decompress(rdpBulk* bulk, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstD
CompressionRatio = ((double) CompressedBytes) / ((double) UncompressedBytes); CompressionRatio = ((double) CompressedBytes) / ((double) UncompressedBytes);
TotalCompressionRatio = ((double) bulk->TotalCompressedBytes) / ((double) bulk->TotalUncompressedBytes); TotalCompressionRatio = ((double) bulk->TotalCompressedBytes) / ((double) bulk->TotalUncompressedBytes);
printf("Compression Ratio: %f Total: %f\n", CompressionRatio, TotalCompressionRatio); printf("Type: %d Flags: 0x%04X Compression Ratio: %f Total: %f %d / %d\n",
type, flags, CompressionRatio, TotalCompressionRatio, CompressedBytes, UncompressedBytes);
} }
#endif #endif
} }
else
{
fprintf(stderr, "Decompression failure!\n");
}
return status; return status;
} }
int bulk_compress(rdpBulk* bulk, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags) int bulk_compress(rdpBulk* bulk, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags)
{ {
UINT32 type;
int status = -1; int status = -1;
UINT32 CompressedBytes; UINT32 CompressedBytes;
UINT32 UncompressedBytes; UINT32 UncompressedBytes;
@ -112,7 +123,7 @@ int bulk_compress(rdpBulk* bulk, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstDat
mppc_set_compression_level(bulk->mppcSend, bulk->CompressionLevel); mppc_set_compression_level(bulk->mppcSend, bulk->CompressionLevel);
status = mppc_compress(bulk->mppcSend, pSrcData, SrcSize, *ppDstData, pDstSize, pFlags); status = mppc_compress(bulk->mppcSend, pSrcData, SrcSize, *ppDstData, pDstSize, pFlags);
if ((status >= 0) && (*pFlags & PACKET_COMPRESSED)) if (status >= 0)
{ {
CompressedBytes = *pDstSize; CompressedBytes = *pDstSize;
UncompressedBytes = SrcSize; UncompressedBytes = SrcSize;
@ -125,10 +136,13 @@ int bulk_compress(rdpBulk* bulk, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstDat
double CompressionRatio; double CompressionRatio;
double TotalCompressionRatio; double TotalCompressionRatio;
type = bulk->CompressionLevel;
CompressionRatio = ((double) CompressedBytes) / ((double) UncompressedBytes); CompressionRatio = ((double) CompressedBytes) / ((double) UncompressedBytes);
TotalCompressionRatio = ((double) bulk->TotalCompressedBytes) / ((double) bulk->TotalUncompressedBytes); TotalCompressionRatio = ((double) bulk->TotalCompressedBytes) / ((double) bulk->TotalUncompressedBytes);
printf("Compression Ratio: %f Total: %f\n", CompressionRatio, TotalCompressionRatio); printf("Type: %d Flags: 0x%04X Compression Ratio: %f Total: %f %d / %d\n",
type, *pFlags, CompressionRatio, TotalCompressionRatio, CompressedBytes, UncompressedBytes);
} }
#endif #endif
} }
@ -140,9 +154,7 @@ void bulk_reset(rdpBulk* bulk)
{ {
mppc_context_reset(bulk->mppcSend); mppc_context_reset(bulk->mppcSend);
mppc_context_reset(bulk->mppcRecv); mppc_context_reset(bulk->mppcRecv);
ncrush_context_reset(bulk->ncrushRecv);
mppc_dec_free(bulk->mppc_dec);
bulk->mppc_dec = mppc_dec_new();
} }
rdpBulk* bulk_new(rdpContext* context) rdpBulk* bulk_new(rdpContext* context)
@ -158,7 +170,7 @@ rdpBulk* bulk_new(rdpContext* context)
bulk->mppcSend = mppc_context_new(1, TRUE); bulk->mppcSend = mppc_context_new(1, TRUE);
bulk->mppcRecv = mppc_context_new(1, FALSE); bulk->mppcRecv = mppc_context_new(1, FALSE);
bulk->mppc_dec = mppc_dec_new(); bulk->ncrushRecv = ncrush_context_new(FALSE);
bulk->CompressionLevel = context->settings->CompressionLevel; bulk->CompressionLevel = context->settings->CompressionLevel;
@ -176,7 +188,7 @@ void bulk_free(rdpBulk* bulk)
mppc_context_free(bulk->mppcSend); mppc_context_free(bulk->mppcSend);
mppc_context_free(bulk->mppcRecv); mppc_context_free(bulk->mppcRecv);
mppc_dec_free(bulk->mppc_dec); ncrush_context_free(bulk->ncrushRecv);
free(bulk); free(bulk);
} }

View File

@ -25,8 +25,7 @@ typedef struct rdp_bulk rdpBulk;
#include "rdp.h" #include "rdp.h"
#include <freerdp/codec/mppc.h> #include <freerdp/codec/mppc.h>
#include <freerdp/codec/mppc_enc.h> #include <freerdp/codec/ncrush.h>
#include <freerdp/codec/mppc_dec.h>
struct rdp_bulk struct rdp_bulk
{ {
@ -35,8 +34,8 @@ struct rdp_bulk
UINT32 CompressionMaxSize; UINT32 CompressionMaxSize;
MPPC_CONTEXT* mppcSend; MPPC_CONTEXT* mppcSend;
MPPC_CONTEXT* mppcRecv; MPPC_CONTEXT* mppcRecv;
NCRUSH_CONTEXT* ncrushRecv;
BYTE OutputBuffer[65536]; BYTE OutputBuffer[65536];
struct rdp_mppc_dec* mppc_dec;
UINT64 TotalCompressedBytes; UINT64 TotalCompressedBytes;
UINT64 TotalUncompressedBytes; UINT64 TotalUncompressedBytes;

View File

@ -2274,7 +2274,8 @@ BOOL rdp_read_multifragment_update_capability_set(wStream* s, UINT16 length, rdp
return FALSE; return FALSE;
Stream_Read_UINT32(s, multifragMaxRequestSize); /* MaxRequestSize (4 bytes) */ Stream_Read_UINT32(s, multifragMaxRequestSize); /* MaxRequestSize (4 bytes) */
if (settings->RemoteFxCodec && settings->MultifragMaxRequestSize < multifragMaxRequestSize)
if (multifragMaxRequestSize < settings->MultifragMaxRequestSize)
settings->MultifragMaxRequestSize = multifragMaxRequestSize; settings->MultifragMaxRequestSize = multifragMaxRequestSize;
return TRUE; return TRUE;

View File

@ -268,6 +268,12 @@ BOOL rdp_client_connect(rdpRdp* rdp)
{ {
connectErrorCode = MCSCONNECTINITIALERROR; connectErrorCode = MCSCONNECTINITIALERROR;
} }
if (!freerdp_get_last_error(rdp->context))
{
freerdp_set_last_error(rdp->context, FREERDP_ERROR_MCS_CONNECT_INITIAL_ERROR);
}
fprintf(stderr, "Error: unable to send MCS Connect Initial\n"); fprintf(stderr, "Error: unable to send MCS Connect Initial\n");
return FALSE; return FALSE;
} }
@ -303,16 +309,16 @@ BOOL rdp_client_redirect(rdpRdp* rdp)
} }
else else
{ {
if (settings->RedirectionFlags & LB_TARGET_NET_ADDRESS) if (settings->RedirectionFlags & LB_TARGET_FQDN)
{
free(settings->ServerHostname);
settings->ServerHostname = _strdup(settings->TargetNetAddress);
}
else if (settings->RedirectionFlags & LB_TARGET_FQDN)
{ {
free(settings->ServerHostname); free(settings->ServerHostname);
settings->ServerHostname = _strdup(settings->RedirectionTargetFQDN); settings->ServerHostname = _strdup(settings->RedirectionTargetFQDN);
} }
else if (settings->RedirectionFlags & LB_TARGET_NET_ADDRESS)
{
free(settings->ServerHostname);
settings->ServerHostname = _strdup(settings->TargetNetAddress);
}
else if (settings->RedirectionFlags & LB_TARGET_NETBIOS_NAME) else if (settings->RedirectionFlags & LB_TARGET_NETBIOS_NAME)
{ {
free(settings->ServerHostname); free(settings->ServerHostname);

View File

@ -342,6 +342,8 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
BYTE fragmentation; BYTE fragmentation;
BYTE compression; BYTE compression;
BYTE compressionFlags; BYTE compressionFlags;
UINT32 DstSize = 0;
BYTE* pDstData = NULL;
rdpTransport* transport; rdpTransport* transport;
status = 0; status = 0;
@ -363,26 +365,20 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
cs = s; cs = s;
next_pos = Stream_GetPosition(s) + size; next_pos = Stream_GetPosition(s) + size;
if (compressionFlags & PACKET_COMPRESSED) if (bulk_decompress(rdp->bulk, Stream_Pointer(s), size, &pDstData, &DstSize, compressionFlags))
{ {
UINT32 DstSize = 0; size = DstSize;
BYTE* pDstData = NULL; cs = StreamPool_Take(transport->ReceivePool, DstSize);
if (bulk_decompress(rdp->bulk, Stream_Pointer(s), size, &pDstData, &DstSize, compressionFlags)) Stream_SetPosition(cs, 0);
{ Stream_Write(cs, pDstData, DstSize);
size = DstSize; Stream_SealLength(cs);
cs = StreamPool_Take(transport->ReceivePool, DstSize); Stream_SetPosition(cs, 0);
}
Stream_SetPosition(cs, 0); else
Stream_Write(cs, pDstData, DstSize); {
Stream_SealLength(cs); fprintf(stderr, "bulk_decompress() failed\n");
Stream_SetPosition(cs, 0); Stream_Seek(s, size);
}
else
{
fprintf(stderr, "bulk_decompress() failed\n");
Stream_Seek(s, size);
}
} }
if (fragmentation == FASTPATH_FRAGMENT_SINGLE) if (fragmentation == FASTPATH_FRAGMENT_SINGLE)
@ -855,6 +851,7 @@ BOOL fastpath_send_update_pdu(rdpFastPath* fastpath, BYTE updateCode, wStream* s
{ {
CompressionMaxSize = bulk_compression_max_size(rdp->bulk); CompressionMaxSize = bulk_compression_max_size(rdp->bulk);
maxLength = (maxLength < CompressionMaxSize) ? maxLength : CompressionMaxSize; maxLength = (maxLength < CompressionMaxSize) ? maxLength : CompressionMaxSize;
maxLength -= 20;
} }
totalLength = Stream_GetPosition(s); totalLength = Stream_GetPosition(s);

View File

@ -65,6 +65,7 @@ BOOL freerdp_connect(freerdp* instance)
/* We always set the return code to 0 before we start the connect sequence*/ /* We always set the return code to 0 before we start the connect sequence*/
connectErrorCode = 0; connectErrorCode = 0;
freerdp_set_last_error(instance->context, FREERDP_ERROR_SUCCESS);
rdp = instance->context->rdp; rdp = instance->context->rdp;
settings = instance->settings; settings = instance->settings;
@ -87,6 +88,12 @@ BOOL freerdp_connect(freerdp* instance)
{ {
connectErrorCode = PREECONNECTERROR; connectErrorCode = PREECONNECTERROR;
} }
if (!freerdp_get_last_error(rdp->context))
{
freerdp_set_last_error(instance->context, FREERDP_ERROR_PRE_CONNECT_FAILED);
}
fprintf(stderr, "%s:%d: freerdp_pre_connect failed\n", __FILE__, __LINE__); fprintf(stderr, "%s:%d: freerdp_pre_connect failed\n", __FILE__, __LINE__);
goto freerdp_connect_finally; goto freerdp_connect_finally;
@ -124,6 +131,11 @@ BOOL freerdp_connect(freerdp* instance)
connectErrorCode = POSTCONNECTERROR; connectErrorCode = POSTCONNECTERROR;
} }
if (!freerdp_get_last_error(rdp->context))
{
freerdp_set_last_error(instance->context, FREERDP_ERROR_POST_CONNECT_FAILED);
}
goto freerdp_connect_finally; goto freerdp_connect_finally;
} }
@ -177,6 +189,8 @@ BOOL freerdp_connect(freerdp* instance)
if (rdp->errorInfo == ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES) if (rdp->errorInfo == ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES)
{ {
connectErrorCode = INSUFFICIENTPRIVILEGESERROR; connectErrorCode = INSUFFICIENTPRIVILEGESERROR;
freerdp_set_last_error(instance->context, FREERDP_ERROR_INSUFFICIENT_PRIVILEGES);
} }
if (!connectErrorCode) if (!connectErrorCode)
@ -184,6 +198,16 @@ BOOL freerdp_connect(freerdp* instance)
connectErrorCode = UNDEFINEDCONNECTERROR; connectErrorCode = UNDEFINEDCONNECTERROR;
} }
if (!freerdp_get_last_error(rdp->context))
{
freerdp_set_last_error(instance->context, FREERDP_ERROR_CONNECT_UNDEFINED);
}
if (!freerdp_get_last_error(rdp->context))
{
freerdp_set_last_error(instance->context, FREERDP_ERROR_CONNECT_UNDEFINED);
}
SetEvent(rdp->transport->connectedEvent); SetEvent(rdp->transport->connectedEvent);
freerdp_connect_finally: freerdp_connect_finally:
@ -496,3 +520,14 @@ void freerdp_free(freerdp* instance)
free(instance); free(instance);
} }
} }
FREERDP_API UINT32 freerdp_get_last_error(rdpContext* context)
{
return context->LastError;
}
FREERDP_API void freerdp_set_last_error(rdpContext* context, UINT32 lastError)
{
fprintf(stderr, "freerdp_set_last_error 0x%x\n", lastError);
context->LastError = lastError;
}

View File

@ -142,6 +142,7 @@ int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, TSG_CHANNEL channel)
if (!proceed) if (!proceed)
{ {
connectErrorCode = CANCELEDBYUSER; connectErrorCode = CANCELEDBYUSER;
freerdp_set_last_error(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
return 0; return 0;
} }

View File

@ -120,6 +120,7 @@ int rpc_send_bind_pdu(rdpRpc* rpc)
if (!proceed) if (!proceed)
{ {
connectErrorCode = CANCELEDBYUSER; connectErrorCode = CANCELEDBYUSER;
freerdp_set_last_error(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
return 0; return 0;
} }

View File

@ -154,9 +154,17 @@ BOOL rts_connect(rdpRpc* rpc)
http_response_print(http_response); http_response_print(http_response);
http_response_free(http_response); http_response_free(http_response);
if (!connectErrorCode && http_response->StatusCode == HTTP_STATUS_DENIED) if (http_response->StatusCode == HTTP_STATUS_DENIED)
{ {
connectErrorCode = AUTHENTICATIONERROR; if (!connectErrorCode)
{
connectErrorCode = AUTHENTICATIONERROR;
}
if (!freerdp_get_last_error(((freerdp*)(rpc->settings->instance))->context))
{
freerdp_set_last_error(((freerdp*)(rpc->settings->instance))->context, FREERDP_ERROR_AUTHENTICATION_FAILED);
}
} }
return FALSE; return FALSE;

View File

@ -153,6 +153,7 @@ int credssp_ntlm_client_init(rdpCredssp* credssp)
if (!proceed) if (!proceed)
{ {
connectErrorCode = CANCELEDBYUSER; connectErrorCode = CANCELEDBYUSER;
freerdp_set_last_error(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
return 0; return 0;
} }

View File

@ -238,12 +238,17 @@ BOOL rdp_set_error_info(rdpRdp* rdp, UINT32 errorInfo)
ErrorInfoEventArgs e; ErrorInfoEventArgs e;
rdpContext* context = rdp->instance->context; rdpContext* context = rdp->instance->context;
rdp->context->LastError = MAKE_FREERDP_ERROR(ERRINFO, errorInfo);
rdp_print_errinfo(rdp->errorInfo); rdp_print_errinfo(rdp->errorInfo);
EventArgsInit(&e, "freerdp"); EventArgsInit(&e, "freerdp");
e.code = rdp->errorInfo; e.code = rdp->errorInfo;
PubSub_OnErrorInfo(context->pubSub, context, &e); PubSub_OnErrorInfo(context->pubSub, context, &e);
} }
else
{
rdp->context->LastError = FREERDP_ERROR_SUCCESS;
}
return TRUE; return TRUE;
} }
@ -1050,7 +1055,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
Stream_SetPosition(s, nextPosition); Stream_SetPosition(s, nextPosition);
} }
} }
else if (channelId == rdp->mcs->messageChannelId) else if (rdp->mcs->messageChannelId && channelId == rdp->mcs->messageChannelId)
{ {
return rdp_recv_message_channel_pdu(rdp, s); return rdp_recv_message_channel_pdu(rdp, s);
} }

View File

@ -48,8 +48,6 @@
#include <freerdp/freerdp.h> #include <freerdp/freerdp.h>
#include <freerdp/settings.h> #include <freerdp/settings.h>
#include <freerdp/utils/debug.h> #include <freerdp/utils/debug.h>
#include <freerdp/codec/mppc_dec.h>
#include <freerdp/codec/mppc_enc.h>
#include <winpr/stream.h> #include <winpr/stream.h>

View File

@ -103,16 +103,16 @@ int rdp_redirection_apply_settings(rdpRdp* rdp)
} }
else else
{ {
if (settings->RedirectionFlags & LB_TARGET_NET_ADDRESS) if (settings->RedirectionFlags & LB_TARGET_FQDN)
{
free(settings->TargetNetAddress);
settings->TargetNetAddress = _strdup(redirection->TargetNetAddress);
}
else if (settings->RedirectionFlags & LB_TARGET_FQDN)
{ {
free(settings->RedirectionTargetFQDN); free(settings->RedirectionTargetFQDN);
settings->RedirectionTargetFQDN = _strdup(redirection->TargetFQDN); settings->RedirectionTargetFQDN = _strdup(redirection->TargetFQDN);
} }
else if (settings->RedirectionFlags & LB_TARGET_NET_ADDRESS)
{
free(settings->TargetNetAddress);
settings->TargetNetAddress = _strdup(redirection->TargetNetAddress);
}
else if (settings->RedirectionFlags & LB_TARGET_NETBIOS_NAME) else if (settings->RedirectionFlags & LB_TARGET_NETBIOS_NAME)
{ {
free(settings->RedirectionTargetNetBiosName); free(settings->RedirectionTargetNetBiosName);

View File

@ -253,7 +253,11 @@ rdpSettings* freerdp_settings_new(DWORD flags)
settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE; settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE;
settings->CompressionEnabled = TRUE; settings->CompressionEnabled = TRUE;
settings->CompressionLevel = PACKET_COMPR_TYPE_64K;
if (settings->ServerMode)
settings->CompressionLevel = PACKET_COMPR_TYPE_64K;
else
settings->CompressionLevel = PACKET_COMPR_TYPE_RDP6;
settings->Authentication = TRUE; settings->Authentication = TRUE;
settings->AuthenticationOnly = FALSE; settings->AuthenticationOnly = FALSE;

View File

@ -71,25 +71,8 @@ void transport_attach(rdpTransport* transport, int sockfd)
transport->TcpOut = transport->TcpIn; transport->TcpOut = transport->TcpIn;
} }
BOOL transport_disconnect(rdpTransport* transport) void transport_stop(rdpTransport* transport)
{ {
BOOL status = TRUE;
if (!transport)
return FALSE;
if (transport->layer == TRANSPORT_LAYER_TLS)
status &= tls_disconnect(transport->TlsIn);
if ((transport->layer == TRANSPORT_LAYER_TSG) || (transport->layer == TRANSPORT_LAYER_TSG_TLS))
{
status &= tsg_disconnect(transport->tsg);
}
else
{
status &= tcp_disconnect(transport->TcpIn);
}
if (transport->async) if (transport->async)
{ {
if (transport->stopEvent) if (transport->stopEvent)
@ -104,6 +87,28 @@ BOOL transport_disconnect(rdpTransport* transport)
transport->stopEvent = NULL; transport->stopEvent = NULL;
} }
} }
}
BOOL transport_disconnect(rdpTransport* transport)
{
BOOL status = TRUE;
if (!transport)
return FALSE;
transport_stop(transport);
if (transport->layer == TRANSPORT_LAYER_TLS)
status &= tls_disconnect(transport->TlsIn);
if ((transport->layer == TRANSPORT_LAYER_TSG) || (transport->layer == TRANSPORT_LAYER_TSG_TLS))
{
status &= tsg_disconnect(transport->tsg);
}
else
{
status &= tcp_disconnect(transport->TcpIn);
}
return status; return status;
} }
@ -239,6 +244,11 @@ BOOL transport_connect_tls(rdpTransport* transport)
if (!connectErrorCode) if (!connectErrorCode)
connectErrorCode = TLSCONNECTERROR; connectErrorCode = TLSCONNECTERROR;
if (!freerdp_get_last_error(((freerdp*)(transport->settings->instance))->context))
{
freerdp_set_last_error(((freerdp*)(transport->settings->instance))->context, FREERDP_ERROR_TLS_CONNECT_FAILED);
}
tls_free(transport->TsgTls); tls_free(transport->TsgTls);
transport->TsgTls = NULL; transport->TsgTls = NULL;
@ -268,6 +278,11 @@ BOOL transport_connect_tls(rdpTransport* transport)
if (!connectErrorCode) if (!connectErrorCode)
connectErrorCode = TLSCONNECTERROR; connectErrorCode = TLSCONNECTERROR;
if (!freerdp_get_last_error(((freerdp*)(transport->settings->instance))->context))
{
freerdp_set_last_error(((freerdp*)(transport->settings->instance))->context, FREERDP_ERROR_TLS_CONNECT_FAILED);
}
tls_free(transport->TlsIn); tls_free(transport->TlsIn);
if (transport->TlsIn == transport->TlsOut) if (transport->TlsIn == transport->TlsOut)
@ -313,6 +328,11 @@ BOOL transport_connect_nla(rdpTransport* transport)
if (!connectErrorCode) if (!connectErrorCode)
connectErrorCode = AUTHENTICATIONERROR; connectErrorCode = AUTHENTICATIONERROR;
if (!freerdp_get_last_error(instance->context))
{
freerdp_set_last_error(instance->context, FREERDP_ERROR_AUTHENTICATION_FAILED);
}
fprintf(stderr, "Authentication failure, check credentials.\n" fprintf(stderr, "Authentication failure, check credentials.\n"
"If credentials are valid, the NTLMSSP implementation may be to blame.\n"); "If credentials are valid, the NTLMSSP implementation may be to blame.\n");
@ -874,7 +894,7 @@ int transport_check_fds(rdpTransport* transport)
{ {
status = transport_read_nonblocking(transport); status = transport_read_nonblocking(transport);
if (status <= 0) if (status < 0 || Stream_GetPosition(transport->ReceiveBuffer) == 0)
return status; return status;
while ((pos = Stream_GetPosition(transport->ReceiveBuffer)) > 0) while ((pos = Stream_GetPosition(transport->ReceiveBuffer)) > 0)
@ -1055,7 +1075,7 @@ static void* transport_client_thread(void* arg)
transport_get_read_handles(transport, (HANDLE*) &handles, &nCount); transport_get_read_handles(transport, (HANDLE*) &handles, &nCount);
status = WaitForMultipleObjects(nCount, handles, FALSE, 100); status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE);
if (transport->layer == TRANSPORT_LAYER_CLOSED) if (transport->layer == TRANSPORT_LAYER_CLOSED)
{ {
rdpRdp* rdp = (rdpRdp*) transport->rdp; rdpRdp* rdp = (rdpRdp*) transport->rdp;
@ -1121,20 +1141,7 @@ void transport_free(rdpTransport* transport)
{ {
if (transport) if (transport)
{ {
if (transport->async) transport_stop(transport);
{
if (transport->stopEvent)
{
SetEvent(transport->stopEvent);
WaitForSingleObject(transport->thread, INFINITE);
CloseHandle(transport->thread);
CloseHandle(transport->stopEvent);
transport->thread = NULL;
transport->stopEvent = NULL;
}
}
if (transport->ReceiveBuffer) if (transport->ReceiveBuffer)
Stream_Release(transport->ReceiveBuffer); Stream_Release(transport->ReceiveBuffer);

View File

@ -92,6 +92,7 @@ BOOL transport_connect_tsg(rdpTransport* transport);
BOOL transport_accept_rdp(rdpTransport* transport); BOOL transport_accept_rdp(rdpTransport* transport);
BOOL transport_accept_tls(rdpTransport* transport); BOOL transport_accept_tls(rdpTransport* transport);
BOOL transport_accept_nla(rdpTransport* transport); BOOL transport_accept_nla(rdpTransport* transport);
void transport_stop(rdpTransport* transport);
int transport_read(rdpTransport* transport, wStream* s); int transport_read(rdpTransport* transport, wStream* s);
int transport_write(rdpTransport* transport, wStream* s); int transport_write(rdpTransport* transport, wStream* s);
void transport_get_fds(rdpTransport* transport, void** rfds, int* rcount); void transport_get_fds(rdpTransport* transport, void** rfds, int* rcount);

View File

@ -696,6 +696,11 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int po
if (instance->VerifyX509Certificate) if (instance->VerifyX509Certificate)
{ {
status = instance->VerifyX509Certificate(instance, pemCert, length, hostname, port, 0); status = instance->VerifyX509Certificate(instance, pemCert, length, hostname, port, 0);
if (status < 0)
{
freerdp_set_last_error(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
}
} }
fprintf(stderr, "VerifyX509Certificate: (length = %d) status: %d\n%s\n", fprintf(stderr, "VerifyX509Certificate: (length = %d) status: %d\n%s\n",
@ -787,8 +792,15 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int po
tls_print_certificate_name_mismatch_error(hostname, common_name, alt_names, alt_names_count); tls_print_certificate_name_mismatch_error(hostname, common_name, alt_names, alt_names_count);
if (instance->VerifyCertificate) if (instance->VerifyCertificate)
{
accept_certificate = instance->VerifyCertificate(instance, subject, issuer, fingerprint); accept_certificate = instance->VerifyCertificate(instance, subject, issuer, fingerprint);
if (!accept_certificate)
{
freerdp_set_last_error(((freerdp*) tls->settings->instance)->context, FREERDP_ERROR_CONNECT_CANCELLED);
}
}
if (!accept_certificate) if (!accept_certificate)
{ {
/* user did not accept, abort and do not add entry in known_hosts file */ /* user did not accept, abort and do not add entry in known_hosts file */
@ -807,8 +819,15 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int po
tls_print_certificate_error(hostname, fingerprint, tls->certificate_store->file); tls_print_certificate_error(hostname, fingerprint, tls->certificate_store->file);
if (instance->VerifyChangedCertificate) if (instance->VerifyChangedCertificate)
{
accept_certificate = instance->VerifyChangedCertificate(instance, subject, issuer, fingerprint, ""); accept_certificate = instance->VerifyChangedCertificate(instance, subject, issuer, fingerprint, "");
if (!accept_certificate)
{
freerdp_set_last_error(((freerdp*) tls->settings->instance)->context, FREERDP_ERROR_CONNECT_CANCELLED);
}
}
if (!accept_certificate) if (!accept_certificate)
{ {
/* user did not accept, abort and do not change known_hosts file */ /* user did not accept, abort and do not change known_hosts file */

View File

@ -125,6 +125,7 @@ extern "C" {
} while(0) } while(0)
WINPR_API void BitDump(const BYTE* buffer, UINT32 length, UINT32 flags); WINPR_API void BitDump(const BYTE* buffer, UINT32 length, UINT32 flags);
WINPR_API UINT32 ReverseBits32(UINT32 bits, UINT32 nbits);
WINPR_API void BitStream_Attach(wBitStream* bs, BYTE* buffer, UINT32 capacity); WINPR_API void BitStream_Attach(wBitStream* bs, BYTE* buffer, UINT32 capacity);

View File

@ -183,6 +183,23 @@ void BitDump(const BYTE* buffer, UINT32 length, UINT32 flags)
printf("\n"); printf("\n");
} }
UINT32 ReverseBits32(UINT32 bits, UINT32 nbits)
{
UINT32 rbits = 0;
do
{
rbits = (rbits | (bits & 1)) << 1;
bits >>= 1;
nbits--;
}
while (nbits > 0);
rbits >>= 1;
return rbits;
}
#if 0 #if 0
/** /**

View File

@ -408,7 +408,7 @@ void InitializeWtsApiStubs(void)
if (!g_WtsApiModule) if (!g_WtsApiModule)
return; return;
pInitWtsApi = GetProcAddress(g_WtsApiModule, "InitWtsApi"); pInitWtsApi = (INIT_WTSAPI_FN) GetProcAddress(g_WtsApiModule, "InitWtsApi");
if (pInitWtsApi) if (pInitWtsApi)
{ {