318 lines
9.1 KiB
NASM
318 lines
9.1 KiB
NASM
IFDEF DBLSPACE_LEGAL
|
|
page ,130
|
|
title DeCompressor
|
|
;-----------------------------------------------------------------------
|
|
; Name: RDCOMP.ASM
|
|
;
|
|
; Routines defined:
|
|
; Decompress32
|
|
;
|
|
; Description:
|
|
; This file holds the code that is responsible for decompressing
|
|
; the compressed data.
|
|
;
|
|
; VxD History:
|
|
; 22-Apr-93 jeffpar Major adaptation and cleanup for MRCI32.386
|
|
;-----------------------------------------------------------------------
|
|
|
|
.386p
|
|
|
|
.xlist
|
|
;; include vmm.inc
|
|
;; include debug.inc
|
|
include mdequ.inc
|
|
.list
|
|
|
|
MD_STAMP equ "SD"
|
|
|
|
;;;-----------------------------------------------------------------------
|
|
;;; Data segment
|
|
;;;-----------------------------------------------------------------------
|
|
;;
|
|
;;VxD_LOCKED_DATA_SEG
|
|
;;
|
|
;; public pLowerBound
|
|
;;pLowerBound dd 0 ; if non-zero, then this is the lowest linear
|
|
;; ; address we treat as *our* error
|
|
;; public pUpperBound
|
|
;;pUpperBound dd 0 ; if non-zero, then this is the highest linear
|
|
;; ; address we treat as *our* error (plus one)
|
|
;; public pPrevPgFltHdlr
|
|
;;pPrevPgFltHdlr dd 0 ; if non-zero, addr of previous page fault hdlr
|
|
;;
|
|
;;VxD_LOCKED_DATA_ENDS
|
|
;;
|
|
;;
|
|
;;VxD_PAGEABLE_DATA_SEG
|
|
_DATA SEGMENT DWORD PUBLIC 'DATA'
|
|
|
|
include decode.inc ; include macros and tables used for decoding
|
|
|
|
public decode_data_end
|
|
decode_data_end label byte
|
|
|
|
;;VxD_PAGEABLE_DATA_ENDS
|
|
_DATA ENDS
|
|
|
|
|
|
;-----------------------------------------------------------------------
|
|
; Code segment
|
|
;-----------------------------------------------------------------------
|
|
|
|
;;VxD_PAGEABLE_CODE_SEG
|
|
_TEXT SEGMENT DWORD USE32 PUBLIC 'CODE'
|
|
ASSUME CS:FLAT, DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
|
|
|
|
|
|
public aCmdAt
|
|
aCmdAt dd CmdAt0,CmdAt1,CmdAt2,CmdAt3,CmdAt4,CmdAt5,CmdAt6,CmdAt7
|
|
|
|
|
|
;-----------------------------------------------------------------------
|
|
; Decompression Algorithm
|
|
; -----------------------
|
|
; Decode the next chunk of text in 'coding_buffer', into the buffer as
|
|
; stated in the 'init'.
|
|
;
|
|
; Entry:
|
|
; CLD
|
|
; EBX == start of cluster (see MRCI32IncDecompress!)
|
|
; ECX == chunk count
|
|
; ESI -> compressed data
|
|
; EDI -> destination buffer
|
|
; EDX == remaining data(low)/bits(high) from last call, 0 if none
|
|
;
|
|
; Exit:
|
|
; If successful, CY clear and:
|
|
; ESI == offset to next byte uncompressed data (if any)
|
|
; EDI == offset to next free byte in dest buffer
|
|
; EDX == remaining data(low)/bits(high) for next call, 0 if none
|
|
;
|
|
; Uses:
|
|
; Everything except EBP
|
|
;-----------------------------------------------------------------------
|
|
|
|
;;BeginProc Decompress32
|
|
public Decompress32
|
|
Decompress32 proc near
|
|
|
|
push ebp
|
|
push ebp ; [esp] is our "chunk_count"
|
|
|
|
;; push ebx
|
|
sub ebx,MAX_12BIT_OFFSET ;
|
|
;; mov [pLowerBound],ebx ;
|
|
;; pop [pUpperBound] ; fault handler enabled *now*
|
|
|
|
mov eax,edx ; remaining data to AX
|
|
shr edx,16 ; move state to low word of EDX
|
|
jnz short @F ; jump if continuing previous state
|
|
lodsw ; new decompression, load initial data
|
|
@@: mov [esp],ecx ; save chunk count
|
|
|
|
DecodeLoop:
|
|
;
|
|
; AX has the remaining bits, DL has the next state
|
|
;
|
|
mov ebp,cbCHUNK ; (ebp) is # bytes left this chunk
|
|
DecodeRestart
|
|
|
|
LastErrSJump equ <FirstErrSJump>
|
|
FirstErrSJump: jmp DecodeError ; put first nice fat jump out of the way
|
|
|
|
irpc c,<01234567>
|
|
CmdAt c
|
|
endm
|
|
jmp CmdAt0
|
|
|
|
irpc c,<01234567>
|
|
LengthAt c
|
|
endm
|
|
|
|
DoGeneralLength ; generate code here to handle large lengths
|
|
|
|
DecodeDone:
|
|
;
|
|
; AX has the remaining bits, DL has the next state -- check chunk status
|
|
;
|
|
test ebp,ebp ; perfect chunk-size decompression?
|
|
jnz DecodeCheckLast ; no, check for last chunk
|
|
|
|
dec dword ptr [esp] ; chunks remaining?
|
|
jz DecodeSuccess ; no, so we're all done
|
|
jmp DecodeLoop ; yes, process them
|
|
|
|
public DecodeError
|
|
DecodeError label near
|
|
stc ; random decomp failure jump target
|
|
jmp short DecodeExit
|
|
|
|
DecodeCheckLast:
|
|
dec dword ptr [esp] ; chunks remaining?
|
|
jnz DecodeError ; yes, then we have an error
|
|
|
|
DecodeSuccess:
|
|
mov dh,1 ; return non-0 EDX indicating state exists
|
|
shl edx,16 ; move state to high word of EDX
|
|
movzx eax,ax ; make sure high word of EAX is clear
|
|
or edx,eax ; EDX == state (and carry is CLEAR)
|
|
|
|
DecodeExit:
|
|
;; mov [pUpperBound],0 ; fault handler disabled *now*
|
|
;; mov [pLowerBound],0 ;
|
|
pop ebp ; throw away our "chunk_count" at [esp]
|
|
pop ebp
|
|
ret
|
|
|
|
;;EndProc Decompress32
|
|
Decompress32 endp
|
|
|
|
|
|
|
|
|
|
|
|
;;VxD_PAGEABLE_CODE_ENDS
|
|
_TEXT ENDS
|
|
|
|
;;
|
|
;;VxD_LOCKED_CODE_SEG
|
|
;;
|
|
;;;-----------------------------------------------------------------------
|
|
;;; Decompress32_Page_Fault
|
|
;;; -----------------------
|
|
;;; Looks for VMM page faults caused by the decompressor. The fault
|
|
;;; must have taken place in the range from [pLowerBound] to [pUpperBound]-1.
|
|
;;; If the fault IS in that range, then we set EIP to DecodeError.
|
|
;;;
|
|
;;; WARNING: this takes advantage of the fact that the decompressor does not
|
|
;;; use the stack; otherwise, we would obviously need to record and re-set ESP
|
|
;;; to a known point as well.
|
|
;;;
|
|
;;; This is in locked code to insure that a subsequent fault doesn't destroy
|
|
;;; the information necessary to process the first (eg, CR2)!
|
|
;;;
|
|
;;; Entry:
|
|
;;; EBX == VM handle
|
|
;;; EBP -> VMM re-entrant stack frame
|
|
;;;
|
|
;;; Uses:
|
|
;;; May use everything except SEG REGS
|
|
;;;-----------------------------------------------------------------------
|
|
;;
|
|
;;BeginProc Decompress32_Page_Fault
|
|
;;;
|
|
;;; Note: the fall-through case is the common one (ie, not our page fault)
|
|
;;;
|
|
;; push eax
|
|
;; mov eax,cr2 ; get faulting address
|
|
;; cmp eax,[pUpperBound]
|
|
;; jb short dpf_maybe ; it might be ours
|
|
;; ; otherwise, definitely not
|
|
;;dpf_prev:
|
|
;; pop eax ; we've been told to preserve everything
|
|
;; jmp [pPrevPgFltHdlr] ; dispatch to real page fault handler
|
|
;; ; (if we installed, then there *is* one)
|
|
;;dpf_maybe:
|
|
;; cmp eax,[pLowerBound]
|
|
;; jb short dpf_prev ; not going to "fix" it
|
|
;;
|
|
;; Trace_Out "Decompress32_Page_Fault: correcting fault on bad cluster"
|
|
;;
|
|
;; mov [ebp].Client_EIP,OFFSET32 DecodeError
|
|
;; pop eax
|
|
;; ret ; we "fixed" it
|
|
;;
|
|
;;EndProc Decompress32_Page_Fault
|
|
;;
|
|
;;VxD_LOCKED_CODE_ENDS
|
|
|
|
|
|
;++
|
|
;
|
|
; ULONG
|
|
; DblsMrcfDecompress (
|
|
; PUCHAR UncompressedBuffer,
|
|
; ULONG UncompressedLength,
|
|
; PUCHAR CompressedBuffer,
|
|
; ULONG CompressedLength,
|
|
; PMRCF_DECOMPRESS WorkSpace
|
|
; )
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This routine decompresses a buffer of StandardCompressed or MaxCompressed
|
|
; data.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; UncompressedBuffer - buffer to receive uncompressed data
|
|
;
|
|
; UncompressedLength - length of UncompressedBuffer
|
|
;
|
|
; NOTE: UncompressedLength must be the EXACT length of the uncompressed
|
|
; data, as Decompress uses this information to detect
|
|
; when decompression is complete. If this value is
|
|
; incorrect, Decompress may crash!
|
|
;
|
|
; CompressedBuffer - buffer containing compressed data
|
|
;
|
|
; CompressedLength - length of CompressedBuffer
|
|
;
|
|
; WorkSpace - pointer to a private work area for use by this operation
|
|
;
|
|
; Return Value:
|
|
;
|
|
; ULONG - Returns the size of the decompressed data in bytes. Returns 0 if
|
|
; there was an error in the decompress.
|
|
;--
|
|
|
|
_TEXT SEGMENT DWORD USE32 PUBLIC 'CODE'
|
|
ASSUME CS:FLAT, DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
|
|
|
|
public _DblsMrcfDecompress@20
|
|
_DblsMrcfDecompress@20 proc near
|
|
|
|
push esi
|
|
push edi
|
|
push ebx
|
|
|
|
mov ecx,dword ptr [esp+20]
|
|
mov edx,ecx
|
|
shr ecx,9
|
|
and edx,512-1
|
|
jz @f
|
|
inc ecx
|
|
sub edx,edx
|
|
@@: mov esi,dword ptr [esp+24]
|
|
mov edi,dword ptr [esp+16]
|
|
mov ebx,edi
|
|
|
|
cld
|
|
lodsd
|
|
cmp ax,MD_STAMP
|
|
je @f
|
|
sub eax,eax
|
|
jz done
|
|
|
|
@@: call Decompress32
|
|
jnc @f
|
|
sub eax,eax
|
|
jz done
|
|
|
|
@@: sub edi,dword ptr [esp+16]
|
|
mov eax,edi
|
|
|
|
done:
|
|
pop ebx
|
|
pop edi
|
|
pop esi
|
|
|
|
ret 20
|
|
|
|
_DblsMrcfDecompress@20 endp
|
|
|
|
_TEXT ENDS
|
|
ENDIF ; DEF DBLSPACE_LEGAL
|
|
end
|
|
|