Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
e3503799
Commit
e3503799
authored
Jul 10, 2015
by
Sebastian Lackner
Committed by
Alexandre Julliard
Jul 10, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Implement RtlDecompressFragment.
Based on a patch by Michael Müller.
parent
cf7a118a
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
212 additions
and
11 deletions
+212
-11
ntdll.spec
dlls/ntdll/ntdll.spec
+1
-1
rtl.c
dlls/ntdll/rtl.c
+210
-6
rtl.c
dlls/ntdll/tests/rtl.c
+0
-3
ntoskrnl.exe.spec
dlls/ntoskrnl.exe/ntoskrnl.exe.spec
+1
-1
No files found.
dlls/ntdll/ntdll.spec
View file @
e3503799
...
...
@@ -513,7 +513,7 @@
@ stdcall RtlDecodePointer(ptr)
# @ stub RtlDecodeSystemPointer
@ stdcall RtlDecompressBuffer(long ptr long ptr long ptr)
@ st
ub RtlDecompressFragment
@ st
dcall RtlDecompressFragment(long ptr long ptr long long ptr ptr)
@ stub RtlDefaultNpAcl
@ stub RtlDelete
@ stdcall RtlDeleteAce(ptr long)
...
...
dlls/ntdll/rtl.c
View file @
e3503799
...
...
@@ -1309,17 +1309,221 @@ NTSTATUS WINAPI RtlCompressBuffer(USHORT format, PUCHAR uncompressed, ULONG unco
}
}
/* decompress a single LZNT1 chunk */
static
UCHAR
*
lznt1_decompress_chunk
(
UCHAR
*
dst
,
ULONG
dst_size
,
UCHAR
*
src
,
ULONG
src_size
)
{
UCHAR
*
src_cur
=
src
,
*
src_end
=
src
+
src_size
;
UCHAR
*
dst_cur
=
dst
,
*
dst_end
=
dst
+
dst_size
;
ULONG
displacement_bits
,
length_bits
;
ULONG
code_displacement
,
code_length
;
WORD
flags
,
code
;
while
(
src_cur
<
src_end
&&
dst_cur
<
dst_end
)
{
flags
=
0x8000
|
*
src_cur
++
;
while
((
flags
&
0xff00
)
&&
src_cur
<
src_end
)
{
if
(
flags
&
1
)
{
/* backwards reference */
if
(
src_cur
+
sizeof
(
WORD
)
>
src_end
)
return
NULL
;
code
=
*
(
WORD
*
)
src_cur
;
src_cur
+=
sizeof
(
WORD
);
/* find length / displacement bits */
for
(
displacement_bits
=
12
;
displacement_bits
>
4
;
displacement_bits
--
)
if
((
1
<<
(
displacement_bits
-
1
))
<
dst_cur
-
dst
)
break
;
length_bits
=
16
-
displacement_bits
;
code_length
=
(
code
&
((
1
<<
length_bits
)
-
1
))
+
3
;
code_displacement
=
(
code
>>
length_bits
)
+
1
;
if
(
dst_cur
<
dst
+
code_displacement
)
return
NULL
;
/* copy bytes of chunk - we can't use memcpy() since source and dest can
* be overlapping, and the same bytes can be repeated over and over again */
while
(
code_length
--
)
{
if
(
dst_cur
>=
dst_end
)
return
dst_cur
;
*
dst_cur
=
*
(
dst_cur
-
code_displacement
);
dst_cur
++
;
}
}
else
{
/* uncompressed data */
if
(
dst_cur
>=
dst_end
)
return
dst_cur
;
*
dst_cur
++
=
*
src_cur
++
;
}
flags
>>=
1
;
}
}
return
dst_cur
;
}
/* decompress data encoded with LZNT1 */
static
NTSTATUS
lznt1_decompress
(
UCHAR
*
dst
,
ULONG
dst_size
,
UCHAR
*
src
,
ULONG
src_size
,
ULONG
offset
,
ULONG
*
final_size
,
UCHAR
*
workspace
)
{
UCHAR
*
src_cur
=
src
,
*
src_end
=
src
+
src_size
;
UCHAR
*
dst_cur
=
dst
,
*
dst_end
=
dst
+
dst_size
;
ULONG
chunk_size
,
block_size
;
WORD
chunk_header
;
UCHAR
*
ptr
;
if
(
src_cur
+
sizeof
(
WORD
)
>
src_end
)
return
STATUS_BAD_COMPRESSION_BUFFER
;
/* skip over chunks with a distance >= 0x1000 to the destination offset */
while
(
offset
>=
0x1000
&&
src_cur
+
sizeof
(
WORD
)
<=
src_end
)
{
chunk_header
=
*
(
WORD
*
)
src_cur
;
src_cur
+=
sizeof
(
WORD
);
if
(
!
chunk_header
)
goto
out
;
chunk_size
=
(
chunk_header
&
0xfff
)
+
1
;
if
(
src_cur
+
chunk_size
>
src_end
)
return
STATUS_BAD_COMPRESSION_BUFFER
;
src_cur
+=
chunk_size
;
offset
-=
0x1000
;
}
/* handle partially included chunk */
if
(
offset
&&
src_cur
+
sizeof
(
WORD
)
<=
src_end
)
{
chunk_header
=
*
(
WORD
*
)
src_cur
;
src_cur
+=
sizeof
(
WORD
);
if
(
!
chunk_header
)
goto
out
;
chunk_size
=
(
chunk_header
&
0xfff
)
+
1
;
if
(
src_cur
+
chunk_size
>
src_end
)
return
STATUS_BAD_COMPRESSION_BUFFER
;
if
(
dst_cur
>=
dst_end
)
goto
out
;
if
(
chunk_header
&
0x8000
)
{
/* compressed chunk */
if
(
!
workspace
)
return
STATUS_ACCESS_VIOLATION
;
ptr
=
lznt1_decompress_chunk
(
workspace
,
0x1000
,
src_cur
,
chunk_size
);
if
(
!
ptr
)
return
STATUS_BAD_COMPRESSION_BUFFER
;
if
(
ptr
-
workspace
>
offset
)
{
block_size
=
min
((
ptr
-
workspace
)
-
offset
,
dst_end
-
dst_cur
);
memcpy
(
dst_cur
,
workspace
+
offset
,
block_size
);
dst_cur
+=
block_size
;
}
}
else
{
/* uncompressed chunk */
if
(
chunk_size
>
offset
)
{
block_size
=
min
(
chunk_size
-
offset
,
dst_end
-
dst_cur
);
memcpy
(
dst_cur
,
src_cur
+
offset
,
block_size
);
dst_cur
+=
block_size
;
}
}
src_cur
+=
chunk_size
;
}
/* handle remaining chunks */
while
(
src_cur
+
sizeof
(
WORD
)
<=
src_end
)
{
chunk_header
=
*
(
WORD
*
)
src_cur
;
src_cur
+=
sizeof
(
WORD
);
if
(
!
chunk_header
)
goto
out
;
chunk_size
=
(
chunk_header
&
0xfff
)
+
1
;
if
(
src_cur
+
chunk_size
>
src_end
)
return
STATUS_BAD_COMPRESSION_BUFFER
;
/* fill space with padding when the previous chunk was decompressed
* to less than 4096 bytes. no padding is needed for the last chunk
* or when the next chunk is truncated */
block_size
=
((
dst_cur
-
dst
)
+
offset
)
&
0xfff
;
if
(
block_size
)
{
block_size
=
0x1000
-
block_size
;
if
(
dst_cur
+
block_size
>=
dst_end
)
goto
out
;
memset
(
dst_cur
,
0
,
block_size
);
dst_cur
+=
block_size
;
}
if
(
dst_cur
>=
dst_end
)
goto
out
;
if
(
chunk_header
&
0x8000
)
{
/* compressed chunk */
dst_cur
=
lznt1_decompress_chunk
(
dst_cur
,
dst_end
-
dst_cur
,
src_cur
,
chunk_size
);
if
(
!
dst_cur
)
return
STATUS_BAD_COMPRESSION_BUFFER
;
}
else
{
/* uncompressed chunk */
block_size
=
min
(
chunk_size
,
dst_end
-
dst_cur
);
memcpy
(
dst_cur
,
src_cur
,
block_size
);
dst_cur
+=
block_size
;
}
src_cur
+=
chunk_size
;
}
out
:
if
(
final_size
)
*
final_size
=
dst_cur
-
dst
;
return
STATUS_SUCCESS
;
}
/******************************************************************************
* RtlDecompressFragment [NTDLL.@]
*/
NTSTATUS
RtlDecompressFragment
(
USHORT
format
,
PUCHAR
uncompressed
,
ULONG
uncompressed_size
,
PUCHAR
compressed
,
ULONG
compressed_size
,
ULONG
offset
,
PULONG
final_size
,
PVOID
workspace
)
{
TRACE
(
"0x%04x, %p, %u, %p, %u, %u, %p, %p
\n
"
,
format
,
uncompressed
,
uncompressed_size
,
compressed
,
compressed_size
,
offset
,
final_size
,
workspace
);
switch
(
format
&
~
COMPRESSION_ENGINE_MAXIMUM
)
{
case
COMPRESSION_FORMAT_LZNT1
:
return
lznt1_decompress
(
uncompressed
,
uncompressed_size
,
compressed
,
compressed_size
,
offset
,
final_size
,
workspace
);
case
COMPRESSION_FORMAT_NONE
:
case
COMPRESSION_FORMAT_DEFAULT
:
return
STATUS_INVALID_PARAMETER
;
default
:
FIXME
(
"format %u not implemented
\n
"
,
format
);
return
STATUS_UNSUPPORTED_COMPRESSION
;
}
}
/******************************************************************************
* RtlDecompressBuffer [NTDLL.@]
*/
NTSTATUS
WINAPI
RtlDecompressBuffer
(
USHORT
CompressionFormat
,
PUCHAR
UncompressedBuffer
,
ULONG
UncompressedBufferSize
,
PUCHAR
CompressedBuffer
,
ULONG
CompressedBufferSize
,
PULONG
FinalUncompressedSize
)
NTSTATUS
WINAPI
RtlDecompressBuffer
(
USHORT
format
,
PUCHAR
uncompressed
,
ULONG
uncompressed_size
,
PUCHAR
compressed
,
ULONG
compressed_size
,
PULONG
final_size
)
{
FIXME
(
"0x%04x, %p, %u, %p, %u, %p :stub
\n
"
,
CompressionFormat
,
UncompressedBuffer
,
UncompressedBufferSize
,
CompressedBuffer
,
CompressedBufferSize
,
FinalUncompressedS
ize
);
TRACE
(
"0x%04x, %p, %u, %p, %u, %p
\n
"
,
format
,
uncompressed
,
uncompressed_size
,
compressed
,
compressed_size
,
final_s
ize
);
return
STATUS_NOT_IMPLEMENTED
;
return
RtlDecompressFragment
(
format
,
uncompressed
,
uncompressed_size
,
compressed
,
compressed_size
,
0
,
final_size
,
NULL
);
}
/***********************************************************************
...
...
dlls/ntdll/tests/rtl.c
View file @
e3503799
...
...
@@ -1663,11 +1663,8 @@ static void test_RtlCompressBuffer(void)
memset
(
buf2
,
0x11
,
sizeof
(
buf2
));
status
=
pRtlDecompressBuffer
(
COMPRESSION_FORMAT_LZNT1
,
buf2
,
sizeof
(
buf2
),
buf1
,
buf_size
,
&
final_size
);
todo_wine
ok
(
status
==
STATUS_SUCCESS
,
"got wrong status 0x%08x
\n
"
,
status
);
todo_wine
ok
(
final_size
==
sizeof
(
test_buffer
),
"got wrong final_size %u
\n
"
,
final_size
);
todo_wine
ok
(
!
memcmp
(
buf2
,
test_buffer
,
sizeof
(
test_buffer
)),
"got wrong decoded data
\n
"
);
ok
(
buf2
[
sizeof
(
test_buffer
)]
==
0x11
,
"too many bytes written
\n
"
);
...
...
dlls/ntoskrnl.exe/ntoskrnl.exe.spec
View file @
e3503799
...
...
@@ -977,7 +977,7 @@
@ stub RtlCustomCPToUnicodeN
@ stdcall RtlDecompressBuffer(long ptr long ptr long ptr) ntdll.RtlDecompressBuffer
@ stub RtlDecompressChunks
@ st
ub
RtlDecompressFragment
@ st
dcall RtlDecompressFragment(long ptr long ptr long long ptr ptr) ntdll.
RtlDecompressFragment
@ stub RtlDelete
@ stdcall RtlDeleteAce(ptr long) ntdll.RtlDeleteAce
@ stdcall RtlDeleteAtomFromAtomTable(ptr long) ntdll.RtlDeleteAtomFromAtomTable
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment