/*++
Xpress decompression function.
Copyright (C) 2008 Matthieu Suiche < msuiche [à] gmail(.)com >
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Module Name:
xpress.c
Abstract:
- Implementation of Xpress decompression function.
Environment:
- User mode
Revision History:
- Matthieu Suiche
--*/
#include
#include
VOID DecompressWin2k3(PBYTE inputBuffer,
PBYTE outputBuffer,
DWORD outputSize,
DWORD inputConsumed);
int main()
{
PBYTE input, output;
HANDLE h;
DWORD readed, index;
printf("Matthieu Suiche (c) 2008 - http://www.msuiche.net\n");
input = VirtualAlloc( NULL, 0x10000, MEM_COMMIT, PAGE_READWRITE );
output = VirtualAlloc( NULL, 0x10000, MEM_COMMIT, PAGE_READWRITE );
h = CreateFile (L"comp-1.dat", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
ReadFile(h, input, 0x10000, &readed, 0);
DecompressWin2k3(input, output, 0x10000, 0);
for (index = 1; index < 0x1000; index++)
{
printf("%02X ", output[index - 1]);
if ((index % 0x10) == 0) printf("\n");
}
VirtualFree(input, 0, 0);
VirtualFree(output, 0, 0);
CloseHandle(h);
return 1;
}
/*++
Function Name: DecompressWin2k3
Overview:
- Informative summary of behavior: The DecompressWin2k3 procedure
decompresses data that was compressed on the server.
Algorithm is "Xpress" and has been implemented for the first time
in Windows XP.
Parameters:
- inputBuffer: A sequence of BYTE containing compressed data.
- outputBuffer: A sequence of BYTE that is an empty buffer. Decompressed
data will be filled into this buffer.
- outputSize: The DWORD value that indicates the size of data in bytes that
can be accommodated in outputBuffer
- inputConsumed: A DWORD reference. At the end of the procedure, this parameter
will have the number of bytes processed in inputBuffer.
Return Values:
- None
--*/
VOID DecompressWin2k3(PBYTE inputBuffer,
PBYTE outputBuffer,
DWORD outputSize,
DWORD inputConsumed)
{
DWORD outputIndex, inputIndex;
DWORD indicator, indicatorBit;
DWORD length;
DWORD offset;
DWORD nibbleIndex;
outputIndex = 0;
inputIndex = 0;
indicator = 0;
indicatorBit = 0;
length = 0;
offset = 0;
nibbleIndex = 0;
while (outputIndex < outputSize)
{
if (indicatorBit == 0)
{
indicator = (inputBuffer[inputIndex + 3] << 24) | (inputBuffer[inputIndex + 2] << 16) |
(inputBuffer[inputIndex + 1] << 8) | inputBuffer[inputIndex];
inputIndex += sizeof(DWORD);
indicatorBit = 32;
}
indicatorBit--;
//* check whether the bit specified by indicatorBit is set or not
//* set in indicator. For example, if indicatorBit has value 4
//* check whether the 4th bit of the value in indicator is set
if (((indicator >> indicatorBit) & 1) == 0)
{
outputBuffer[outputIndex] = inputBuffer[inputIndex];
inputIndex += sizeof(BYTE);
outputIndex += sizeof(BYTE);
}
else
{
length = (inputBuffer[inputIndex + 1] << 8) | inputBuffer[inputIndex];
inputIndex += sizeof(WORD);
offset = length / 8;
length = length % 8;
if (length == 7)
{
if (nibbleIndex == 0)
{
nibbleIndex = inputIndex;
length = inputBuffer[inputIndex] % 16;
inputIndex += sizeof(BYTE);
}
else
{
length = inputBuffer[nibbleIndex] / 16;
nibbleIndex = 0;
}
if (length == 15)
{
length = inputBuffer[inputIndex];
inputIndex += sizeof(BYTE);
if (length == 255)
{
length = (inputBuffer[inputIndex + 1] << 8) | inputBuffer[inputIndex];
inputIndex += sizeof(WORD);
length -= (15 + 7);
}
length += 15;
}
length += 7;
}
length += 3;
while (length != 0)
{
outputBuffer[outputIndex] = outputBuffer[outputIndex - offset - 1];
outputIndex += sizeof(BYTE);
length -= sizeof(BYTE);
}
}
}
return;
}