Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
wine
Manage
Activity
Members
Labels
Plan
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Terraform modules
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Alanas Tebuev
wine
Commits
682f6adc
Commit
682f6adc
authored
14 years ago
by
Andrey Turkin
Committed by
Alexandre Julliard
14 years ago
Browse files
Options
Downloads
Patches
Plain Diff
imagehlp: Add tests for ImageGetDigestStream.
Based on a patch by Juan Lang.
parent
6d8d3d74
No related branches found
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
dlls/imagehlp/tests/Makefile.in
+1
-0
1 addition, 0 deletions
dlls/imagehlp/tests/Makefile.in
dlls/imagehlp/tests/image.c
+356
-0
356 additions, 0 deletions
dlls/imagehlp/tests/image.c
with
357 additions
and
0 deletions
dlls/imagehlp/tests/Makefile.in
+
1
−
0
View file @
682f6adc
...
...
@@ -5,6 +5,7 @@ VPATH = @srcdir@
TESTDLL
=
imagehlp.dll
C_SRCS
=
\
image.c
\
integrity.c
@MAKE_TEST_RULES@
This diff is collapsed.
Click to expand it.
dlls/imagehlp/tests/image.c
0 → 100644
+
356
−
0
View file @
682f6adc
/*
* Copyright 2008 Juan Lang
* Copyright 2010 Andrey Turkin
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include
<stdio.h>
#include
<stdarg.h>
#define NONAMELESSUNION
#include
<windef.h>
#include
<winbase.h>
#include
<winver.h>
#include
<winnt.h>
#include
<imagehlp.h>
#include
"wine/test.h"
static
HMODULE
hImageHlp
;
static
BOOL
(
WINAPI
*
pImageGetDigestStream
)(
HANDLE
,
DWORD
,
DIGEST_FUNCTION
,
DIGEST_HANDLE
);
/* minimal PE file image */
#define VA_START 0x400000
#define FILE_PE_START 0x50
#define NUM_SECTIONS 3
#define FILE_TEXT 0x200
#define RVA_TEXT 0x1000
#define RVA_BSS 0x2000
#define FILE_IDATA 0x400
#define RVA_IDATA 0x3000
#define FILE_TOTAL 0x600
#define RVA_TOTAL 0x4000
#include
<pshpack1.h>
struct
Imports
{
IMAGE_IMPORT_DESCRIPTOR
descriptors
[
2
];
IMAGE_THUNK_DATA32
original_thunks
[
2
];
IMAGE_THUNK_DATA32
thunks
[
2
];
struct
__IMPORT_BY_NAME
{
WORD
hint
;
char
funcname
[
0x20
];
}
ibn
;
char
dllname
[
0x10
];
};
#define EXIT_PROCESS (VA_START+RVA_IDATA+FIELD_OFFSET(struct Imports, thunks[0]))
static
struct
_PeImage
{
IMAGE_DOS_HEADER
dos_header
;
char
__alignment1
[
FILE_PE_START
-
sizeof
(
IMAGE_DOS_HEADER
)];
IMAGE_NT_HEADERS32
nt_headers
;
IMAGE_SECTION_HEADER
sections
[
NUM_SECTIONS
];
char
__alignment2
[
FILE_TEXT
-
FILE_PE_START
-
sizeof
(
IMAGE_NT_HEADERS32
)
-
NUM_SECTIONS
*
sizeof
(
IMAGE_SECTION_HEADER
)];
unsigned
char
text_section
[
FILE_IDATA
-
FILE_TEXT
];
struct
Imports
idata_section
;
char
__alignment3
[
FILE_TOTAL
-
FILE_IDATA
-
sizeof
(
struct
Imports
)];
}
bin
=
{
/* dos header */
{
IMAGE_DOS_SIGNATURE
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
{},
0
,
0
,
{},
FILE_PE_START
},
/* alignment before PE header */
{},
/* nt headers */
{
IMAGE_NT_SIGNATURE
,
/* basic headers - 3 sections, no symbols, EXE file */
{
IMAGE_FILE_MACHINE_I386
,
NUM_SECTIONS
,
0
,
0
,
0
,
sizeof
(
IMAGE_OPTIONAL_HEADER32
),
IMAGE_FILE_32BIT_MACHINE
|
IMAGE_FILE_EXECUTABLE_IMAGE
},
/* optional header */
{
IMAGE_NT_OPTIONAL_HDR32_MAGIC
,
4
,
0
,
FILE_IDATA
-
FILE_TEXT
,
FILE_TOTAL
-
FILE_IDATA
+
FILE_IDATA
-
FILE_TEXT
,
0x400
,
RVA_TEXT
,
RVA_TEXT
,
RVA_BSS
,
VA_START
,
0x1000
,
0x200
,
4
,
0
,
1
,
0
,
4
,
0
,
0
,
RVA_TOTAL
,
FILE_TEXT
,
0
,
IMAGE_SUBSYSTEM_WINDOWS_GUI
,
0
,
0x200000
,
0x1000
,
0x100000
,
0x1000
,
0
,
0x10
,
{{
0
,
0
},
{
RVA_IDATA
,
sizeof
(
struct
Imports
)}
}
}
},
/* sections */
{
{
".text"
,
{
0x100
},
RVA_TEXT
,
FILE_IDATA
-
FILE_TEXT
,
FILE_TEXT
,
0
,
0
,
0
,
0
,
IMAGE_SCN_CNT_CODE
|
IMAGE_SCN_MEM_EXECUTE
|
IMAGE_SCN_MEM_READ
},
{
".bss"
,
{
0x400
},
RVA_BSS
,
0
,
0
,
0
,
0
,
0
,
0
,
IMAGE_SCN_CNT_UNINITIALIZED_DATA
|
IMAGE_SCN_MEM_READ
|
IMAGE_SCN_MEM_WRITE
},
{
".idata"
,
{
sizeof
(
struct
Imports
)},
RVA_IDATA
,
FILE_TOTAL
-
FILE_IDATA
,
FILE_IDATA
,
0
,
0
,
0
,
0
,
IMAGE_SCN_CNT_INITIALIZED_DATA
|
IMAGE_SCN_MEM_READ
|
IMAGE_SCN_MEM_WRITE
}
},
/* alignment before first section */
{},
/* .text section */
{
0x31
,
0xC0
,
/* xor eax, eax */
0xFF
,
0x25
,
EXIT_PROCESS
&
0xFF
,
(
EXIT_PROCESS
>>
8
)
&
0xFF
,
(
EXIT_PROCESS
>>
16
)
&
0xFF
,
(
EXIT_PROCESS
>>
24
)
&
0xFF
,
/* jmp ExitProcess */
0
},
/* .idata section */
{
{
{{
RVA_IDATA
+
FIELD_OFFSET
(
struct
Imports
,
original_thunks
)},
0
,
0
,
RVA_IDATA
+
FIELD_OFFSET
(
struct
Imports
,
dllname
),
RVA_IDATA
+
FIELD_OFFSET
(
struct
Imports
,
thunks
)
},
{{
0
},
0
,
0
,
0
,
0
}
},
{{{
RVA_IDATA
+
FIELD_OFFSET
(
struct
Imports
,
ibn
)}},
{{
0
}}},
{{{
RVA_IDATA
+
FIELD_OFFSET
(
struct
Imports
,
ibn
)}},
{{
0
}}},
{
0
,
"ExitProcess"
},
"KERNEL32.DLL"
},
/* final alignment */
{}
};
#include
<poppack.h>
struct
blob
{
DWORD
cb
;
BYTE
*
pb
;
};
struct
expected_blob
{
DWORD
cb
;
const
void
*
pb
;
};
struct
update_accum
{
DWORD
cUpdates
;
struct
blob
*
updates
;
};
struct
expected_update_accum
{
DWORD
cUpdates
;
const
struct
expected_blob
*
updates
;
};
static
BOOL
WINAPI
accumulating_stream_output
(
DIGEST_HANDLE
handle
,
BYTE
*
pb
,
DWORD
cb
)
{
struct
update_accum
*
accum
=
(
struct
update_accum
*
)
handle
;
BOOL
ret
=
FALSE
;
if
(
accum
->
cUpdates
)
accum
->
updates
=
HeapReAlloc
(
GetProcessHeap
(),
0
,
accum
->
updates
,
(
accum
->
cUpdates
+
1
)
*
sizeof
(
struct
blob
));
else
accum
->
updates
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
struct
blob
));
if
(
accum
->
updates
)
{
struct
blob
*
blob
=
&
accum
->
updates
[
accum
->
cUpdates
];
blob
->
pb
=
HeapAlloc
(
GetProcessHeap
(),
0
,
cb
);
if
(
blob
->
pb
)
{
memcpy
(
blob
->
pb
,
pb
,
cb
);
blob
->
cb
=
cb
;
ret
=
TRUE
;
}
accum
->
cUpdates
++
;
}
return
ret
;
}
static
void
check_updates
(
LPCSTR
header
,
const
struct
expected_update_accum
*
expected
,
const
struct
update_accum
*
got
)
{
DWORD
i
;
ok
(
expected
->
cUpdates
==
got
->
cUpdates
,
"%s: expected %d updates, got %d
\n
"
,
header
,
expected
->
cUpdates
,
got
->
cUpdates
);
for
(
i
=
0
;
i
<
min
(
expected
->
cUpdates
,
got
->
cUpdates
);
i
++
)
{
ok
(
expected
->
updates
[
i
].
cb
==
got
->
updates
[
i
].
cb
,
"%s, update %d: expected %d bytes, got %d
\n
"
,
header
,
i
,
expected
->
updates
[
i
].
cb
,
got
->
updates
[
i
].
cb
);
if
(
expected
->
updates
[
i
].
cb
&&
expected
->
updates
[
i
].
cb
==
got
->
updates
[
i
].
cb
)
ok
(
!
memcmp
(
expected
->
updates
[
i
].
pb
,
got
->
updates
[
i
].
pb
,
got
->
updates
[
i
].
cb
),
"%s, update %d: unexpected value
\n
"
,
header
,
i
);
}
}
/* Frees the updates stored in accum */
static
void
free_updates
(
struct
update_accum
*
accum
)
{
DWORD
i
;
for
(
i
=
0
;
i
<
accum
->
cUpdates
;
i
++
)
HeapFree
(
GetProcessHeap
(),
0
,
accum
->
updates
[
i
].
pb
);
HeapFree
(
GetProcessHeap
(),
0
,
accum
->
updates
);
accum
->
updates
=
NULL
;
accum
->
cUpdates
=
0
;
}
static
const
struct
expected_blob
b1
[]
=
{
{
FILE_PE_START
,
&
bin
},
/* with zeroed Checksum/SizeOfInitializedData/SizeOfImage fields */
{
sizeof
(
bin
.
nt_headers
),
&
bin
.
nt_headers
},
{
sizeof
(
bin
.
sections
),
&
bin
.
sections
},
{
FILE_IDATA
-
FILE_TEXT
,
&
bin
.
text_section
},
{
sizeof
(
bin
.
idata_section
.
descriptors
[
0
].
u
.
OriginalFirstThunk
),
&
bin
.
idata_section
.
descriptors
[
0
].
u
.
OriginalFirstThunk
},
{
FIELD_OFFSET
(
struct
Imports
,
thunks
)
-
FIELD_OFFSET
(
struct
Imports
,
descriptors
[
0
].
Name
),
&
bin
.
idata_section
.
descriptors
[
0
].
Name
},
{
FILE_TOTAL
-
FILE_IDATA
-
FIELD_OFFSET
(
struct
Imports
,
ibn
),
&
bin
.
idata_section
.
ibn
}
};
static
const
struct
expected_update_accum
a1
=
{
sizeof
(
b1
)
/
sizeof
(
b1
[
0
]),
b1
};
static
const
struct
expected_blob
b2
[]
=
{
{
FILE_PE_START
,
&
bin
},
/* with zeroed Checksum/SizeOfInitializedData/SizeOfImage fields */
{
sizeof
(
bin
.
nt_headers
),
&
bin
.
nt_headers
},
{
sizeof
(
bin
.
sections
),
&
bin
.
sections
},
{
FILE_IDATA
-
FILE_TEXT
,
&
bin
.
text_section
},
{
FILE_TOTAL
-
FILE_IDATA
,
&
bin
.
idata_section
}
};
static
const
struct
expected_update_accum
a2
=
{
sizeof
(
b2
)
/
sizeof
(
b2
[
0
]),
b2
};
/* Creates a test file and returns a handle to it. The file's path is returned
* in temp_file, which must be at least MAX_PATH characters in length.
*/
static
HANDLE
create_temp_file
(
char
*
temp_file
)
{
HANDLE
file
=
INVALID_HANDLE_VALUE
;
char
temp_path
[
MAX_PATH
];
if
(
GetTempPathA
(
sizeof
(
temp_path
),
temp_path
))
{
if
(
GetTempFileNameA
(
temp_path
,
"img"
,
0
,
temp_file
))
file
=
CreateFileA
(
temp_file
,
GENERIC_READ
|
GENERIC_WRITE
,
0
,
NULL
,
CREATE_ALWAYS
,
FILE_ATTRIBUTE_NORMAL
,
NULL
);
}
return
file
;
}
static
void
update_checksum
(
void
)
{
WORD
const
*
ptr
;
DWORD
size
;
DWORD
sum
=
0
;
bin
.
nt_headers
.
OptionalHeader
.
CheckSum
=
0
;
for
(
ptr
=
(
WORD
const
*
)
&
bin
,
size
=
(
sizeof
(
bin
)
+
1
)
/
sizeof
(
WORD
);
size
>
0
;
ptr
++
,
size
--
)
{
sum
+=
*
ptr
;
if
(
HIWORD
(
sum
)
!=
0
)
{
sum
=
LOWORD
(
sum
)
+
HIWORD
(
sum
);
}
}
sum
=
(
WORD
)(
LOWORD
(
sum
)
+
HIWORD
(
sum
));
sum
+=
sizeof
(
bin
);
bin
.
nt_headers
.
OptionalHeader
.
CheckSum
=
sum
;
}
static
void
test_get_digest_stream
(
void
)
{
BOOL
ret
;
HANDLE
file
;
char
temp_file
[
MAX_PATH
];
DWORD
count
;
struct
update_accum
accum
=
{
0
,
NULL
};
SetLastError
(
0xdeadbeef
);
ret
=
pImageGetDigestStream
(
NULL
,
0
,
NULL
,
NULL
);
todo_wine
ok
(
!
ret
&&
GetLastError
()
==
ERROR_INVALID_PARAMETER
,
"expected ERROR_INVALID_PARAMETER, got %d
\n
"
,
GetLastError
());
file
=
create_temp_file
(
temp_file
);
if
(
file
==
INVALID_HANDLE_VALUE
)
{
skip
(
"couldn't create temp file
\n
"
);
return
;
}
SetLastError
(
0xdeadbeef
);
ret
=
pImageGetDigestStream
(
file
,
0
,
NULL
,
NULL
);
todo_wine
ok
(
!
ret
&&
GetLastError
()
==
ERROR_INVALID_PARAMETER
,
"expected ERROR_INVALID_PARAMETER, got %d
\n
"
,
GetLastError
());
SetLastError
(
0xdeadbeef
);
ret
=
pImageGetDigestStream
(
NULL
,
0
,
accumulating_stream_output
,
&
accum
);
todo_wine
ok
(
!
ret
&&
GetLastError
()
==
ERROR_INVALID_PARAMETER
,
"expected ERROR_INVALID_PARAMETER, got %d
\n
"
,
GetLastError
());
/* Even with "valid" parameters, it fails with an empty file */
SetLastError
(
0xdeadbeef
);
ret
=
pImageGetDigestStream
(
file
,
0
,
accumulating_stream_output
,
&
accum
);
todo_wine
ok
(
!
ret
&&
GetLastError
()
==
ERROR_INVALID_PARAMETER
,
"expected ERROR_INVALID_PARAMETER, got %d
\n
"
,
GetLastError
());
/* Finally, with a valid executable in the file, it succeeds. Note that
* the file pointer need not be positioned at the beginning.
*/
update_checksum
();
WriteFile
(
file
,
&
bin
,
sizeof
(
bin
),
&
count
,
NULL
);
FlushFileBuffers
(
file
);
/* zero out some fields ImageGetDigestStream would zero out */
bin
.
nt_headers
.
OptionalHeader
.
CheckSum
=
0
;
bin
.
nt_headers
.
OptionalHeader
.
SizeOfInitializedData
=
0
;
bin
.
nt_headers
.
OptionalHeader
.
SizeOfImage
=
0
;
ret
=
pImageGetDigestStream
(
file
,
0
,
accumulating_stream_output
,
&
accum
);
todo_wine
ok
(
ret
,
"ImageGetDigestStream failed: %d
\n
"
,
GetLastError
());
todo_wine
check_updates
(
"flags = 0"
,
&
a1
,
&
accum
);
free_updates
(
&
accum
);
ret
=
pImageGetDigestStream
(
file
,
CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO
,
accumulating_stream_output
,
&
accum
);
todo_wine
ok
(
ret
,
"ImageGetDigestStream failed: %d
\n
"
,
GetLastError
());
todo_wine
check_updates
(
"flags = CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO"
,
&
a2
,
&
accum
);
free_updates
(
&
accum
);
CloseHandle
(
file
);
DeleteFileA
(
temp_file
);
}
START_TEST
(
image
)
{
hImageHlp
=
LoadLibraryA
(
"imagehlp.dll"
);
if
(
!
hImageHlp
)
{
win_skip
(
"ImageHlp unavailable
\n
"
);
return
;
}
pImageGetDigestStream
=
(
void
*
)
GetProcAddress
(
hImageHlp
,
"ImageGetDigestStream"
);
if
(
!
pImageGetDigestStream
)
{
win_skip
(
"ImageGetDigestStream function is not available
\n
"
);
}
else
{
test_get_digest_stream
();
}
FreeLibrary
(
hImageHlp
);
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment