Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
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-cw
Commits
682f6adc
Commit
682f6adc
authored
Jul 18, 2010
by
Andrey Turkin
Committed by
Alexandre Julliard
Jul 30, 2010
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
imagehlp: Add tests for ImageGetDigestStream.
Based on a patch by Juan Lang.
parent
6d8d3d74
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
357 additions
and
0 deletions
+357
-0
Makefile.in
dlls/imagehlp/tests/Makefile.in
+1
-0
image.c
dlls/imagehlp/tests/image.c
+356
-0
No files found.
dlls/imagehlp/tests/Makefile.in
View file @
682f6adc
...
...
@@ -5,6 +5,7 @@ VPATH = @srcdir@
TESTDLL
=
imagehlp.dll
C_SRCS
=
\
image.c
\
integrity.c
@MAKE_TEST_RULES@
dlls/imagehlp/tests/image.c
0 → 100644
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
);
}
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