libfreerdp-core: improve MPPC compress/decompress function definitions

This commit is contained in:
Marc-André Moreau 2014-03-11 21:42:27 -04:00
parent 37e037ee71
commit 85049299e0
4 changed files with 108 additions and 136 deletions

View File

@ -46,8 +46,8 @@ typedef struct _MPPC_CONTEXT MPPC_CONTEXT;
extern "C" {
#endif
FREERDP_API UINT32 mppc_compress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE* pDstData, UINT32* pSize);
FREERDP_API UINT32 mppc_decompress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE** ppDstData, UINT32* pSize, UINT32 flags);
FREERDP_API int mppc_compress(MPPC_CONTEXT* mppc, BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstData, UINT32* pDstSize, UINT32* pFlags);
FREERDP_API int mppc_decompress(MPPC_CONTEXT* mppc, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags);
FREERDP_API void mppc_set_compression_level(MPPC_CONTEXT* mppc, DWORD CompressionLevel);
FREERDP_API void mppc_context_reset(MPPC_CONTEXT* mppc);

View File

@ -72,7 +72,7 @@ const UINT32 MPPC_MATCH_TABLE[256] =
//#define DEBUG_MPPC 1
UINT32 mppc_decompress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE** ppDstData, UINT32* pSize, UINT32 flags)
int mppc_decompress(MPPC_CONTEXT* mppc, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags)
{
BYTE Literal;
BYTE* SrcPtr;
@ -92,7 +92,7 @@ UINT32 mppc_decompress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE** ppDstData, UIN
HistoryBufferEnd = &HistoryBuffer[HistoryBufferSize - 1];
CompressionLevel = mppc->CompressionLevel;
BitStream_Attach(bs, pSrcData, *pSize);
BitStream_Attach(bs, pSrcData, SrcSize);
BitStream_Fetch(bs);
if (flags & PACKET_AT_FRONT)
@ -113,12 +113,13 @@ UINT32 mppc_decompress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE** ppDstData, UIN
if (!(flags & PACKET_COMPRESSED))
{
CopyMemory(HistoryPtr, pSrcData, *pSize);
HistoryPtr += *pSize;
HistoryOffset += *pSize;
CopyMemory(HistoryPtr, pSrcData, SrcSize);
HistoryPtr += SrcSize;
HistoryOffset += SrcSize;
mppc->HistoryPtr = HistoryPtr;
mppc->HistoryOffset = HistoryOffset;
*ppDstData = HistoryPtr;
*pDstSize = SrcSize;
return 1;
}
@ -214,6 +215,7 @@ UINT32 mppc_decompress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE** ppDstData, UIN
else
{
/* Invalid CopyOffset Encoding */
return -1;
}
}
else /* RDP4 */
@ -251,6 +253,7 @@ UINT32 mppc_decompress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE** ppDstData, UIN
else
{
/* Invalid CopyOffset Encoding */
return -1;
}
}
@ -414,6 +417,7 @@ UINT32 mppc_decompress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE** ppDstData, UIN
else
{
/* Invalid LengthOfMatch Encoding */
return -1;
}
#ifdef DEBUG_MPPC
@ -455,16 +459,15 @@ UINT32 mppc_decompress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE** ppDstData, UIN
}
}
*pSize = (UINT32) (HistoryPtr - mppc->HistoryPtr);
*pDstSize = (UINT32) (HistoryPtr - mppc->HistoryPtr);
*ppDstData = mppc->HistoryPtr;
mppc->HistoryPtr = HistoryPtr;
return 1;
}
UINT32 mppc_compress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE* pDstData, UINT32* pSize)
int mppc_compress(MPPC_CONTEXT* mppc, BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstData, UINT32* pDstSize, UINT32* pFlags)
{
UINT32 Flags;
BYTE* pSrcPtr;
BYTE* pSrcEnd;
BYTE* pDstEnd;
@ -488,23 +491,23 @@ UINT32 mppc_compress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE* pDstData, UINT32*
HistoryPtr = mppc->HistoryPtr;
HistoryOffset = mppc->HistoryOffset;
BitStream_Attach(bs, pDstData, *pSize);
BitStream_Attach(bs, pDstData, SrcSize);
if (((HistoryOffset + *pSize) < (HistoryBufferSize - 3)) && HistoryOffset)
if (((HistoryOffset + SrcSize) < (HistoryBufferSize - 3)) && HistoryOffset)
{
Flags = 0;
*pFlags = 0;
}
else
{
HistoryOffset = 0;
Flags = PACKET_AT_FRONT;
*pFlags = PACKET_AT_FRONT;
}
HistoryPtr = &(HistoryBuffer[HistoryOffset]);
pSrcPtr = pSrcData;
pSrcEnd = &(pSrcData[*pSize - 1]);
pDstEnd = &(pDstData[*pSize - 1]);
pSrcEnd = &(pSrcData[SrcSize - 1]);
pDstEnd = &(pDstData[*pDstSize - 1]);
while (pSrcPtr < (pSrcEnd - 2))
{
@ -527,12 +530,12 @@ UINT32 mppc_compress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE* pDstData, UINT32*
(&MatchPtr[1] > mppc->HistoryPtr) || (MatchPtr == HistoryBuffer) ||
(MatchPtr == &HistoryPtr[-1]) || (MatchPtr == HistoryPtr))
{
if (((bs->position / 8) + 2) > (*pSize - 1))
if (((bs->position / 8) + 2) > (SrcSize - 1))
{
Flags |= PACKET_FLUSHED;
*pFlags |= PACKET_FLUSHED;
ZeroMemory(HistoryBuffer, HistoryBufferSize);
ZeroMemory(mppc->MatchBuffer, sizeof(mppc->MatchBuffer));
return Flags;
return 1;
}
accumulator = Sym1;
@ -577,12 +580,12 @@ UINT32 mppc_compress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE* pDstData, UINT32*
/* Encode CopyOffset */
if (((bs->position / 8) + 7) > (*pSize - 1))
if (((bs->position / 8) + 7) > (SrcSize - 1))
{
Flags = PACKET_FLUSHED;
*pFlags = PACKET_FLUSHED;
ZeroMemory(HistoryBuffer, HistoryBufferSize);
ZeroMemory(mppc->MatchBuffer, sizeof(mppc->MatchBuffer));
return Flags;
return 1;
}
if (CompressionLevel) /* RDP5 */
@ -732,12 +735,12 @@ UINT32 mppc_compress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE* pDstData, UINT32*
while (pSrcPtr <= pSrcEnd)
{
if (((bs->position / 8) + 2) > (*pSize - 1))
if (((bs->position / 8) + 2) > (SrcSize - 1))
{
Flags |= PACKET_FLUSHED;
*pFlags |= PACKET_FLUSHED;
ZeroMemory(HistoryBuffer, HistoryBufferSize);
ZeroMemory(mppc->MatchBuffer, sizeof(mppc->MatchBuffer));
return Flags;
return 1;
}
accumulator = *pSrcPtr;
@ -763,9 +766,9 @@ UINT32 mppc_compress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE* pDstData, UINT32*
BitStream_Flush(bs);
Flags |= PACKET_COMPRESSED;
Flags |= CompressionLevel;
*pSize = ((bs->position + 7) / 8);
*pFlags |= PACKET_COMPRESSED;
*pFlags |= CompressionLevel;
*pDstSize = ((bs->position + 7) / 8);
mppc->HistoryPtr = HistoryPtr;
mppc->HistoryOffset = HistoryPtr - HistoryBuffer;
@ -774,7 +777,7 @@ UINT32 mppc_compress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE* pDstData, UINT32*
printf("\n");
#endif
return Flags;
return 1;
}
void mppc_set_compression_level(MPPC_CONTEXT* mppc, DWORD CompressionLevel)

View File

@ -706,38 +706,41 @@ const BYTE TEST_MPPC_BELLS_RDP5[] =
int test_MppcCompressBellsRdp5()
{
UINT32 size;
UINT32 flags;
int status;
UINT32 Flags;
UINT32 SrcSize;
BYTE* pSrcData;
UINT32 DstSize;
MPPC_CONTEXT* mppc;
UINT32 expectedSize;
BYTE OutputBuffer[65536];
mppc = mppc_context_new(1, TRUE);
size = sizeof(TEST_MPPC_BELLS) - 1;
SrcSize = sizeof(TEST_MPPC_BELLS) - 1;
pSrcData = (BYTE*) TEST_MPPC_BELLS;
DstSize = sizeof(OutputBuffer);
expectedSize = sizeof(TEST_MPPC_BELLS_RDP5) - 1;
flags = mppc_compress(mppc, pSrcData, OutputBuffer, &size);
status = mppc_compress(mppc, pSrcData, SrcSize, OutputBuffer, &DstSize, &Flags);
printf("flags: 0x%04X size: %d\n", flags, size);
printf("Flags: 0x%04X DstSize: %d\n", Flags, DstSize);
if (size != expectedSize)
if (DstSize != expectedSize)
{
printf("MppcCompressBellsRdp5: output size mismatch: Actual: %d, Expected: %d\n", size, expectedSize);
printf("MppcCompressBellsRdp5: output size mismatch: Actual: %d, Expected: %d\n", DstSize, expectedSize);
return -1;
}
if (memcmp(OutputBuffer, TEST_MPPC_BELLS_RDP5, size) != 0)
if (memcmp(OutputBuffer, TEST_MPPC_BELLS_RDP5, DstSize) != 0)
{
printf("MppcCompressBellsRdp5: output mismatch\n");
printf("Actual\n");
BitDump(OutputBuffer, size * 8, 0);
BitDump(OutputBuffer, DstSize * 8, 0);
printf("Expected\n");
BitDump(TEST_MPPC_BELLS_RDP5, size * 8, 0);
BitDump(TEST_MPPC_BELLS_RDP5, DstSize * 8, 0);
return -1;
}
@ -749,38 +752,41 @@ int test_MppcCompressBellsRdp5()
int test_MppcCompressBellsRdp4()
{
UINT32 size;
UINT32 flags;
int status;
UINT32 Flags;
BYTE* pSrcData;
UINT32 SrcSize;
UINT32 DstSize;
MPPC_CONTEXT* mppc;
UINT32 expectedSize;
BYTE OutputBuffer[65536];
mppc = mppc_context_new(0, TRUE);
size = sizeof(TEST_MPPC_BELLS) - 1;
SrcSize = sizeof(TEST_MPPC_BELLS) - 1;
pSrcData = (BYTE*) TEST_MPPC_BELLS;
expectedSize = sizeof(TEST_MPPC_BELLS_RDP4) - 1;
DstSize = sizeof(OutputBuffer);
flags = mppc_compress(mppc, pSrcData, OutputBuffer, &size);
status = mppc_compress(mppc, pSrcData, SrcSize, OutputBuffer, &DstSize, &Flags);
printf("flags: 0x%04X size: %d\n", flags, size);
printf("flags: 0x%04X size: %d\n", Flags, DstSize);
if (size != expectedSize)
if (DstSize != expectedSize)
{
printf("MppcCompressBellsRdp4: output size mismatch: Actual: %d, Expected: %d\n", size, expectedSize);
printf("MppcCompressBellsRdp4: output size mismatch: Actual: %d, Expected: %d\n", DstSize, expectedSize);
return -1;
}
if (memcmp(OutputBuffer, TEST_MPPC_BELLS_RDP4, size) != 0)
if (memcmp(OutputBuffer, TEST_MPPC_BELLS_RDP4, DstSize) != 0)
{
printf("MppcCompressBellsRdp4: output mismatch\n");
printf("Actual\n");
BitDump(OutputBuffer, size * 8, 0);
BitDump(OutputBuffer, DstSize * 8, 0);
printf("Expected\n");
BitDump(TEST_MPPC_BELLS_RDP4, size * 8, 0);
BitDump(TEST_MPPC_BELLS_RDP4, DstSize * 8, 0);
return -1;
}
@ -792,30 +798,32 @@ int test_MppcCompressBellsRdp4()
int test_MppcDecompressBellsRdp5()
{
UINT32 size;
UINT32 flags;
int status;
UINT32 Flags;
BYTE* pSrcData;
UINT32 SrcSize;
UINT32 DstSize;
MPPC_CONTEXT* mppc;
UINT32 expectedSize;
BYTE* pDstData = NULL;
mppc = mppc_context_new(1, FALSE);
size = sizeof(TEST_MPPC_BELLS_RDP5) - 1;
SrcSize = sizeof(TEST_MPPC_BELLS_RDP5) - 1;
pSrcData = (BYTE*) TEST_MPPC_BELLS_RDP5;
flags = PACKET_AT_FRONT | PACKET_COMPRESSED | 1;
Flags = PACKET_AT_FRONT | PACKET_COMPRESSED | 1;
expectedSize = sizeof(TEST_MPPC_BELLS) - 1;
flags = mppc_decompress(mppc, pSrcData, &pDstData, &size, flags);
printf("flags: 0x%04X size: %d\n", flags, size);
status = mppc_decompress(mppc, pSrcData, SrcSize, &pDstData, &DstSize, Flags);
printf("flags: 0x%04X size: %d\n", Flags, DstSize);
if (size != expectedSize)
if (DstSize != expectedSize)
{
printf("MppcDecompressBellsRdp5: output size mismatch: Actual: %d, Expected: %d\n", size, expectedSize);
printf("MppcDecompressBellsRdp5: output size mismatch: Actual: %d, Expected: %d\n", DstSize, expectedSize);
return -1;
}
if (memcmp(pDstData, TEST_MPPC_BELLS, size) != 0)
if (memcmp(pDstData, TEST_MPPC_BELLS, DstSize) != 0)
{
printf("MppcDecompressBellsRdp5: output mismatch\n");
return -1;
@ -828,30 +836,32 @@ int test_MppcDecompressBellsRdp5()
int test_MppcDecompressBellsRdp4()
{
UINT32 size;
UINT32 flags;
int status;
UINT32 Flags;
BYTE* pSrcData;
UINT32 SrcSize;
UINT32 DstSize;
MPPC_CONTEXT* mppc;
UINT32 expectedSize;
BYTE* pDstData = NULL;
mppc = mppc_context_new(0, FALSE);
size = sizeof(TEST_MPPC_BELLS_RDP4) - 1;
SrcSize = sizeof(TEST_MPPC_BELLS_RDP4) - 1;
pSrcData = (BYTE*) TEST_MPPC_BELLS_RDP4;
flags = PACKET_AT_FRONT | PACKET_COMPRESSED | 0;
Flags = PACKET_AT_FRONT | PACKET_COMPRESSED | 0;
expectedSize = sizeof(TEST_MPPC_BELLS) - 1;
flags = mppc_decompress(mppc, pSrcData, &pDstData, &size, flags);
printf("flags: 0x%04X size: %d\n", flags, size);
status = mppc_decompress(mppc, pSrcData, SrcSize, &pDstData, &DstSize, Flags);
printf("flags: 0x%04X size: %d\n", Flags, DstSize);
if (size != expectedSize)
if (DstSize != expectedSize)
{
printf("MppcDecompressBellsRdp4: output size mismatch: Actual: %d, Expected: %d\n", size, expectedSize);
printf("MppcDecompressBellsRdp4: output size mismatch: Actual: %d, Expected: %d\n", DstSize, expectedSize);
return -1;
}
if (memcmp(pDstData, TEST_MPPC_BELLS, size) != 0)
if (memcmp(pDstData, TEST_MPPC_BELLS, DstSize) != 0)
{
printf("MppcDecompressBellsRdp4: output mismatch\n");
return -1;
@ -864,99 +874,72 @@ int test_MppcDecompressBellsRdp4()
int test_MppcCompressBufferRdp5()
{
UINT32 size;
UINT32 flags;
int status;
UINT32 Flags;
BYTE* pSrcData;
UINT32 SrcSize;
UINT32 DstSize;
MPPC_CONTEXT* mppc;
UINT32 expectedSize;
BYTE OutputBuffer[65536];
MPPC_CONTEXT* mppcRecv;
BYTE* pDstData = NULL;
mppc = mppc_context_new(1, TRUE);
size = sizeof(TEST_RDP5_UNCOMPRESSED_DATA);
SrcSize = sizeof(TEST_RDP5_UNCOMPRESSED_DATA);
pSrcData = (BYTE*) TEST_RDP5_UNCOMPRESSED_DATA;
expectedSize = sizeof(TEST_RDP5_COMPRESSED_DATA);
DstSize = sizeof(OutputBuffer);
pDstData = OutputBuffer;
flags = mppc_compress(mppc, pSrcData, OutputBuffer, &size);
printf("flags: 0x%04X size: %d\n", flags, size);
status = mppc_compress(mppc, pSrcData, SrcSize, pDstData, &DstSize, &Flags);
printf("flags: 0x%04X size: %d\n", Flags, DstSize);
mppcRecv = mppc_context_new(1, FALSE);
pSrcData = (BYTE*) OutputBuffer;
flags = PACKET_AT_FRONT | PACKET_COMPRESSED | 1;
expectedSize = sizeof(TEST_RDP5_UNCOMPRESSED_DATA);
flags = mppc_decompress(mppcRecv, pSrcData, &pDstData, &size, flags);
printf("flags: 0x%04X size: %d\n", flags, size);
if (size != expectedSize)
if (DstSize != expectedSize)
{
printf("MppcCompressBufferRdp5: output size mismatch: Actual: %d, Expected: %d\n", size, expectedSize);
printf("MppcCompressBufferRdp5: output size mismatch: Actual: %d, Expected: %d\n", DstSize, expectedSize);
return -1;
}
if (memcmp(pDstData, TEST_RDP5_UNCOMPRESSED_DATA, size) != 0)
{
printf("MppcCompressBufferRdp5: output mismatch: Decompress(Compress(X)) != X\n");
return -1;
}
/* Compare against Microsoft implementation */
size = sizeof(TEST_RDP5_UNCOMPRESSED_DATA);
pSrcData = (BYTE*) TEST_RDP5_UNCOMPRESSED_DATA;
expectedSize = sizeof(TEST_RDP5_COMPRESSED_DATA);
mppc_context_reset(mppc);
flags = mppc_compress(mppc, pSrcData, OutputBuffer, &size);
printf("flags: 0x%04X size: %d\n", flags, size);
if (size != expectedSize)
{
printf("MppcCompressBufferRdp5: output size mismatch: Actual: %d, Expected: %d\n", size, expectedSize);
return -1;
}
if (memcmp(OutputBuffer, TEST_RDP5_COMPRESSED_DATA, size) != 0)
if (memcmp(OutputBuffer, TEST_RDP5_COMPRESSED_DATA, DstSize) != 0)
{
printf("MppcCompressBufferRdp5: output mismatch: compressed output does not match Microsoft implementation\n");
return -1;
}
mppc_context_free(mppc);
mppc_context_free(mppcRecv);
return 0;
}
int test_MppcDecompressBufferRdp5()
{
UINT32 size;
UINT32 flags;
int status;
UINT32 Flags;
BYTE* pSrcData;
UINT32 SrcSize;
UINT32 DstSize;
MPPC_CONTEXT* mppc;
UINT32 expectedSize;
BYTE* pDstData = NULL;
mppc = mppc_context_new(1, FALSE);
size = sizeof(TEST_RDP5_COMPRESSED_DATA);
SrcSize = sizeof(TEST_RDP5_COMPRESSED_DATA);
pSrcData = (BYTE*) TEST_RDP5_COMPRESSED_DATA;
flags = PACKET_AT_FRONT | PACKET_COMPRESSED | 1;
Flags = PACKET_AT_FRONT | PACKET_COMPRESSED | 1;
expectedSize = sizeof(TEST_RDP5_UNCOMPRESSED_DATA);
flags = mppc_decompress(mppc, pSrcData, &pDstData, &size, flags);
printf("flags: 0x%04X size: %d\n", flags, size);
status = mppc_decompress(mppc, pSrcData, SrcSize, &pDstData, &DstSize, Flags);
printf("flags: 0x%04X size: %d\n", Flags, DstSize);
if (size != expectedSize)
if (DstSize != expectedSize)
{
printf("MppcDecompressBufferRdp5: output size mismatch: Actual: %d, Expected: %d\n", size, expectedSize);
printf("MppcDecompressBufferRdp5: output size mismatch: Actual: %d, Expected: %d\n", DstSize, expectedSize);
return -1;
}
if (memcmp(pDstData, TEST_RDP5_UNCOMPRESSED_DATA, size) != 0)
if (memcmp(pDstData, TEST_RDP5_UNCOMPRESSED_DATA, DstSize) != 0)
{
printf("MppcDecompressBufferRdp5: output mismatch\n");
return -1;
@ -987,7 +970,5 @@ int TestFreeRDPCodecMppc(int argc, char* argv[])
if (test_MppcDecompressBufferRdp5() < 0)
return -1;
//test_mppc_old();
return 0;
}

View File

@ -26,7 +26,6 @@
int bulk_decompress(rdpBulk* bulk, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags)
{
int status = -1;
UINT32 size;
UINT32 roff = 0;
UINT32 rlen = 0;
UINT32 type = flags & 0x0F;
@ -34,19 +33,13 @@ int bulk_decompress(rdpBulk* bulk, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstD
switch (type)
{
case PACKET_COMPR_TYPE_8K:
size = SrcSize;
mppc_set_compression_level(bulk->mppcRecv, 0);
mppc_decompress(bulk->mppcRecv, pSrcData, ppDstData, &size, flags);
*pDstSize = size;
status = 1;
status = mppc_decompress(bulk->mppcRecv, pSrcData, SrcSize, ppDstData, pDstSize, flags);
break;
case PACKET_COMPR_TYPE_64K:
size = SrcSize;
mppc_set_compression_level(bulk->mppcRecv, 1);
mppc_decompress(bulk->mppcRecv, pSrcData, ppDstData, &size, flags);
*pDstSize = size;
status = 1;
status = mppc_decompress(bulk->mppcRecv, pSrcData, SrcSize, ppDstData, pDstSize, flags);
break;
case PACKET_COMPR_TYPE_RDP6:
@ -69,17 +62,12 @@ int bulk_decompress(rdpBulk* bulk, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstD
int bulk_compress(rdpBulk* bulk, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags)
{
UINT32 size;
UINT32 flags;
int status = -1;
size = SrcSize;
flags = mppc_compress(bulk->mppcSend, pSrcData, bulk->OutputBuffer, &size);
*pFlags = flags;
*pDstSize = size;
*ppDstData = bulk->OutputBuffer;
status = 1;
*pDstSize = sizeof(bulk->OutputBuffer);
status = mppc_compress(bulk->mppcSend, pSrcData, SrcSize, *ppDstData, pDstSize, pFlags);
return status;
}