BSOne.SFC/Tocsg.Lib/VCL/Tocsg.NTDLL.Decompress.pas

154 lines
5.5 KiB
Plaintext

{*******************************************************}
{ }
{ Tocsg.NTDLL.Decompress }
{ }
{ Copyright (C) 2022 kku }
{ }
{*******************************************************}
unit Tocsg.NTDLL.Decompress;
interface
uses
SysUtils, Winapi.Windows;
const
COMPRESSION_FORMAT_NONE = 0;
COMPRESSION_FORMAT_DEFAULT = 1;
COMPRESSION_FORMAT_LZNT1 = 2;
COMPRESSION_FORMAT_XPRESS = 3;
COMPRESSION_FORMAT_XPRESS_HUFF = 4;
STATUS_SUCCESS = 0;
STATUS_ACCESS_DENIED = $C0000022;
type
TRtlHeader = record
arrSig: array[0..3] of AnsiChar;
dwSize: DWORD;
end;
NTSTATUS = DWORD;
ULONG = DWORD;
PULONG = ^ULONG;
PVOID = Pointer;
USHORT = WORD;
UCHAR = Byte;
PUCHAR = ^UCHAR;
PWSTR = PWideChar;
TRtlGetCompressionWorkSpaceSize = function(CompressionFormatAndEngine: USHORT;
CompressBufferWorkSpaceSize: PULONG;
CompressFragmentWorkSpaceSize: PULONG): NTSTATUS; stdcall;
TRtlDecompressBufferEx = function(CompressionFormat: USHORT;
UncompressedBuffer: PUCHAR;
UncompressedBufferSize: ULONG;
CompressedBuffer: PUCHAR;
CompressedBufferSize: ULONG;
FinalUncompressedSize: PULONG;
WorkSpace: PVOID): NTSTATUS; stdcall;
function RtlGetCompressionWorkSpaceSize(CompressionFormatAndEngine: USHORT;
CompressBufferWorkSpaceSize: PULONG;
CompressFragmentWorkSpaceSize: PULONG): NTSTATUS; // stdcall external 'ntdll.dll';
function RtlDecompressBufferEx(CompressionFormat: USHORT;
UncompressedBuffer: PUCHAR;
UncompressedBufferSize: ULONG;
CompressedBuffer: PUCHAR;
CompressedBufferSize: ULONG;
FinalUncompressedSize: PULONG;
WorkSpace: PVOID): NTSTATUS; // stdcall external 'ntdll.dll';
function RtlDecompress(pSrc, pDest: Pointer; dwSrcSize, dwDecompSize, dwCompFormat: DWORD): DWORD;
implementation
var
_hNtdll: THandle = 0;
_fnRtlGetCompressionWorkSpaceSize: TRtlGetCompressionWorkSpaceSize = nil;
_fnRtlDecompressBufferEx: TRtlDecompressBufferEx = nil;
function InitNtdllDecompProcedure: Boolean;
begin
if _hNtdll = 0 then
begin
_hNtdll := GetModuleHandle('ntdll.dll');
if _hNtdll <> 0 then
begin
@_fnRtlGetCompressionWorkSpaceSize := GetProcAddress(_hNtdll, 'RtlGetCompressionWorkSpaceSize');
@_fnRtlDecompressBufferEx := GetProcAddress(_hNtdll, 'RtlDecompressBufferEx');
end;
end;
Result := _hNtdll <> 0;
end;
function RtlGetCompressionWorkSpaceSize(CompressionFormatAndEngine: USHORT;
CompressBufferWorkSpaceSize: PULONG;
CompressFragmentWorkSpaceSize: PULONG): NTSTATUS;
begin
if InitNtdllDecompProcedure and Assigned(_fnRtlGetCompressionWorkSpaceSize) then
Result := _fnRtlGetCompressionWorkSpaceSize(CompressionFormatAndEngine,
CompressBufferWorkSpaceSize,
CompressFragmentWorkSpaceSize)
else
Result := STATUS_ACCESS_DENIED;
end;
function RtlDecompressBufferEx(CompressionFormat: USHORT;
UncompressedBuffer: PUCHAR;
UncompressedBufferSize: ULONG;
CompressedBuffer: PUCHAR;
CompressedBufferSize: ULONG;
FinalUncompressedSize: PULONG;
WorkSpace: PVOID): NTSTATUS;
begin
if InitNtdllDecompProcedure and Assigned(_fnRtlDecompressBufferEx) then
Result := _fnRtlDecompressBufferEx(CompressionFormat,
UncompressedBuffer,
UncompressedBufferSize,
CompressedBuffer,
CompressedBufferSize,
FinalUncompressedSize,
WorkSpace)
else
Result := STATUS_ACCESS_DENIED;
end;
function RtlDecompress(pSrc, pDest: Pointer; dwSrcSize, dwDecompSize, dwCompFormat: DWORD): DWORD;
var
dwOutSize,
dwResult,
dwCompBufWorkSpaceSize,
dwCompFragWorkSpaceSize: DWORD;
pWorkSpace: array of AnsiChar;
begin
Result := 0;
dwResult := RtlGetCompressionWorkSpaceSize(dwCompFormat,
@dwCompBufWorkSpaceSize,
@dwCompFragWorkSpaceSize);
if dwResult <> STATUS_SUCCESS then
exit;
dwOutSize := 0;
SetLength(pWorkSpace, dwCompBufWorkSpaceSize);
dwResult := RtlDecompressBufferEx(dwCompFormat,
pDest,
dwDecompSize,
pSrc,
dwSrcSize,
@dwOutSize,
pWorkSpace);
if dwResult = STATUS_SUCCESS then
Result := dwOutSize;
end;
end.