4 * Copyright 1998 Patrik Stridvall
5 * Copyright 2003 Mike McCormack
6 * Copyright 2009 Owen Rudge for CodeWeavers
7 * Copyright 2010 Juan Lang
8 * Copyright 2010 Andrey Turkin
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(imagehlp
);
39 * These functions are partially documented at:
40 * http://www.cs.auckland.ac.nz/~pgut001/pubs/authenticode.txt
47 /***********************************************************************
48 * IMAGEHLP_GetNTHeaders (INTERNAL)
50 * Return the IMAGE_NT_HEADERS for a PE file, after validating magic
51 * numbers and distinguishing between 32-bit and 64-bit files.
53 static int IMAGEHLP_GetNTHeaders(HANDLE handle
, DWORD
*pe_offset
, IMAGE_NT_HEADERS32
*nt32
, IMAGE_NT_HEADERS64
*nt64
)
55 IMAGE_DOS_HEADER dos_hdr
;
59 TRACE("handle %p\n", handle
);
61 if ((!nt32
) || (!nt64
))
64 /* read the DOS header */
65 count
= SetFilePointer(handle
, 0, NULL
, FILE_BEGIN
);
67 if (count
== INVALID_SET_FILE_POINTER
)
72 r
= ReadFile(handle
, &dos_hdr
, sizeof dos_hdr
, &count
, NULL
);
77 if (count
!= sizeof dos_hdr
)
80 /* verify magic number of 'MZ' */
81 if (dos_hdr
.e_magic
!= IMAGE_DOS_SIGNATURE
)
84 if (pe_offset
!= NULL
)
85 *pe_offset
= dos_hdr
.e_lfanew
;
87 /* read the PE header */
88 count
= SetFilePointer(handle
, dos_hdr
.e_lfanew
, NULL
, FILE_BEGIN
);
90 if (count
== INVALID_SET_FILE_POINTER
)
95 r
= ReadFile(handle
, nt32
, sizeof(IMAGE_NT_HEADERS32
), &count
, NULL
);
100 if (count
!= sizeof(IMAGE_NT_HEADERS32
))
103 /* verify NT signature */
104 if (nt32
->Signature
!= IMAGE_NT_SIGNATURE
)
107 /* check if we have a 32-bit or 64-bit executable */
108 switch (nt32
->OptionalHeader
.Magic
)
110 case IMAGE_NT_OPTIONAL_HDR32_MAGIC
:
113 case IMAGE_NT_OPTIONAL_HDR64_MAGIC
:
114 /* Re-read as 64-bit */
116 count
= SetFilePointer(handle
, dos_hdr
.e_lfanew
, NULL
, FILE_BEGIN
);
118 if (count
== INVALID_SET_FILE_POINTER
)
123 r
= ReadFile(handle
, nt64
, sizeof(IMAGE_NT_HEADERS64
), &count
, NULL
);
128 if (count
!= sizeof(IMAGE_NT_HEADERS64
))
131 /* verify NT signature */
132 if (nt64
->Signature
!= IMAGE_NT_SIGNATURE
)
141 /***********************************************************************
142 * IMAGEHLP_GetSecurityDirOffset (INTERNAL)
144 * Read a file's PE header, and return the offset and size of the
145 * security directory.
147 static BOOL
IMAGEHLP_GetSecurityDirOffset( HANDLE handle
,
148 DWORD
*pdwOfs
, DWORD
*pdwSize
)
150 IMAGE_NT_HEADERS32 nt_hdr32
;
151 IMAGE_NT_HEADERS64 nt_hdr64
;
152 IMAGE_DATA_DIRECTORY
*sd
;
155 ret
= IMAGEHLP_GetNTHeaders(handle
, NULL
, &nt_hdr32
, &nt_hdr64
);
158 sd
= &nt_hdr32
.OptionalHeader
.DataDirectory
[IMAGE_FILE_SECURITY_DIRECTORY
];
159 else if (ret
== HDR_NT64
)
160 sd
= &nt_hdr64
.OptionalHeader
.DataDirectory
[IMAGE_FILE_SECURITY_DIRECTORY
];
164 TRACE("ret = %d size = %lx addr = %lx\n", ret
, sd
->Size
, sd
->VirtualAddress
);
167 *pdwOfs
= sd
->VirtualAddress
;
172 /***********************************************************************
173 * IMAGEHLP_SetSecurityDirOffset (INTERNAL)
175 * Read a file's PE header, and update the offset and size of the
176 * security directory.
178 static BOOL
IMAGEHLP_SetSecurityDirOffset(HANDLE handle
,
179 DWORD dwOfs
, DWORD dwSize
)
181 IMAGE_NT_HEADERS32 nt_hdr32
;
182 IMAGE_NT_HEADERS64 nt_hdr64
;
183 IMAGE_DATA_DIRECTORY
*sd
;
184 int ret
, nt_hdr_size
= 0;
190 ret
= IMAGEHLP_GetNTHeaders(handle
, &pe_offset
, &nt_hdr32
, &nt_hdr64
);
194 sd
= &nt_hdr32
.OptionalHeader
.DataDirectory
[IMAGE_FILE_SECURITY_DIRECTORY
];
197 nt_hdr_size
= sizeof(IMAGE_NT_HEADERS32
);
199 else if (ret
== HDR_NT64
)
201 sd
= &nt_hdr64
.OptionalHeader
.DataDirectory
[IMAGE_FILE_SECURITY_DIRECTORY
];
204 nt_hdr_size
= sizeof(IMAGE_NT_HEADERS64
);
210 sd
->VirtualAddress
= dwOfs
;
212 TRACE("size = %lx addr = %lx\n", sd
->Size
, sd
->VirtualAddress
);
214 /* write the header back again */
215 count
= SetFilePointer(handle
, pe_offset
, NULL
, FILE_BEGIN
);
217 if (count
== INVALID_SET_FILE_POINTER
)
222 r
= WriteFile(handle
, nt_hdr
, nt_hdr_size
, &count
, NULL
);
227 if (count
!= nt_hdr_size
)
233 /***********************************************************************
234 * IMAGEHLP_GetCertificateOffset (INTERNAL)
236 * Read a file's PE header, and return the offset and size of the
237 * security directory.
239 static BOOL
IMAGEHLP_GetCertificateOffset( HANDLE handle
, DWORD num
,
240 DWORD
*pdwOfs
, DWORD
*pdwSize
)
242 DWORD size
, count
, offset
, len
, sd_VirtualAddr
;
245 r
= IMAGEHLP_GetSecurityDirOffset( handle
, &sd_VirtualAddr
, &size
);
250 /* take the n'th certificate */
253 /* read the length of the current certificate */
254 count
= SetFilePointer( handle
, sd_VirtualAddr
+ offset
,
256 if( count
== INVALID_SET_FILE_POINTER
)
258 r
= ReadFile( handle
, &len
, sizeof len
, &count
, NULL
);
261 if( count
!= sizeof len
)
264 /* check the certificate is not too big or too small */
265 if( len
< sizeof len
)
267 if( len
> (size
-offset
) )
272 /* calculate the offset of the next certificate */
275 /* padded out to the nearest 8-byte boundary */
277 offset
+= 8 - (len
% 8);
283 *pdwOfs
= sd_VirtualAddr
+ offset
;
286 TRACE("len = %lx addr = %lx\n", len
, sd_VirtualAddr
+ offset
);
291 /***********************************************************************
292 * IMAGEHLP_RecalculateChecksum (INTERNAL)
294 * Update the NT header checksum for the specified file.
296 static BOOL
IMAGEHLP_RecalculateChecksum(HANDLE handle
)
298 DWORD FileLength
, count
, HeaderSum
, pe_offset
, nt_hdr_size
;
299 IMAGE_NT_HEADERS32 nt_hdr32
;
300 IMAGE_NT_HEADERS64 nt_hdr64
;
308 TRACE("handle %p\n", handle
);
310 ret
= IMAGEHLP_GetNTHeaders(handle
, &pe_offset
, &nt_hdr32
, &nt_hdr64
);
314 CheckSum
= &nt_hdr32
.OptionalHeader
.CheckSum
;
317 nt_hdr_size
= sizeof(IMAGE_NT_HEADERS32
);
319 else if (ret
== HDR_NT64
)
321 CheckSum
= &nt_hdr64
.OptionalHeader
.CheckSum
;
324 nt_hdr_size
= sizeof(IMAGE_NT_HEADERS64
);
329 hMapping
= CreateFileMappingW(handle
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
334 BaseAddress
= MapViewOfFile(hMapping
, FILE_MAP_READ
, 0, 0, 0);
338 CloseHandle(hMapping
);
342 FileLength
= GetFileSize(handle
, NULL
);
345 CheckSumMappedFile(BaseAddress
, FileLength
, &HeaderSum
, CheckSum
);
347 UnmapViewOfFile(BaseAddress
);
348 CloseHandle(hMapping
);
352 /* write the header back again */
353 count
= SetFilePointer(handle
, pe_offset
, NULL
, FILE_BEGIN
);
355 if (count
== INVALID_SET_FILE_POINTER
)
360 r
= WriteFile(handle
, nt_hdr
, nt_hdr_size
, &count
, NULL
);
365 if (count
!= nt_hdr_size
)
374 /***********************************************************************
375 * ImageAddCertificate (IMAGEHLP.@)
377 * Adds the specified certificate to the security directory of
381 BOOL WINAPI
ImageAddCertificate(
382 HANDLE FileHandle
, LPWIN_CERTIFICATE Certificate
, PDWORD Index
)
384 DWORD size
= 0, count
= 0, offset
= 0, sd_VirtualAddr
= 0, index
= 0;
386 const size_t cert_hdr_size
= sizeof hdr
- sizeof hdr
.bCertificate
;
389 TRACE("(%p, %p, %p)\n", FileHandle
, Certificate
, Index
);
391 r
= IMAGEHLP_GetSecurityDirOffset(FileHandle
, &sd_VirtualAddr
, &size
);
393 /* If we've already got a security directory, find the end of it */
394 if ((r
) && (sd_VirtualAddr
!= 0))
396 /* Check if the security directory is at the end of the file.
397 If not, we should probably relocate it. */
398 if (GetFileSize(FileHandle
, NULL
) != sd_VirtualAddr
+ size
)
400 FIXME("Security directory already present but not located at EOF, not adding certificate\n");
402 SetLastError(ERROR_NOT_SUPPORTED
);
406 while (offset
< size
)
408 /* read the length of the current certificate */
409 count
= SetFilePointer (FileHandle
, sd_VirtualAddr
+ offset
,
412 if (count
== INVALID_SET_FILE_POINTER
)
415 r
= ReadFile(FileHandle
, &hdr
, cert_hdr_size
, &count
, NULL
);
420 if (count
!= cert_hdr_size
)
423 /* check the certificate is not too big or too small */
424 if (hdr
.dwLength
< cert_hdr_size
)
427 if (hdr
.dwLength
> (size
-offset
))
430 /* next certificate */
431 offset
+= hdr
.dwLength
;
433 /* padded out to the nearest 8-byte boundary */
434 if (hdr
.dwLength
% 8)
435 offset
+= 8 - (hdr
.dwLength
% 8);
440 count
= SetFilePointer (FileHandle
, sd_VirtualAddr
+ offset
, NULL
, FILE_BEGIN
);
442 if (count
== INVALID_SET_FILE_POINTER
)
447 sd_VirtualAddr
= SetFilePointer(FileHandle
, 0, NULL
, FILE_END
);
449 if (sd_VirtualAddr
== INVALID_SET_FILE_POINTER
)
453 /* Write the certificate to the file */
454 r
= WriteFile(FileHandle
, Certificate
, Certificate
->dwLength
, &count
, NULL
);
459 /* Pad out if necessary */
460 if (Certificate
->dwLength
% 8)
465 WriteFile(FileHandle
, null
, 8 - (Certificate
->dwLength
% 8), &count
, NULL
);
467 size
+= 8 - (Certificate
->dwLength
% 8);
470 size
+= Certificate
->dwLength
;
472 /* Update the security directory offset and size */
473 if (!IMAGEHLP_SetSecurityDirOffset(FileHandle
, sd_VirtualAddr
, size
))
476 if (!IMAGEHLP_RecalculateChecksum(FileHandle
))
484 /***********************************************************************
485 * ImageEnumerateCertificates (IMAGEHLP.@)
487 BOOL WINAPI
ImageEnumerateCertificates(
488 HANDLE handle
, WORD TypeFilter
, PDWORD CertificateCount
,
489 PDWORD Indices
, DWORD IndexCount
)
491 DWORD size
, count
, offset
, sd_VirtualAddr
, index
;
493 const size_t cert_hdr_size
= sizeof hdr
- sizeof hdr
.bCertificate
;
496 TRACE("%p %hd %p %p %ld\n",
497 handle
, TypeFilter
, CertificateCount
, Indices
, IndexCount
);
499 r
= IMAGEHLP_GetSecurityDirOffset( handle
, &sd_VirtualAddr
, &size
);
505 *CertificateCount
= 0;
506 while( offset
< size
)
508 /* read the length of the current certificate */
509 count
= SetFilePointer( handle
, sd_VirtualAddr
+ offset
,
511 if( count
== INVALID_SET_FILE_POINTER
)
513 r
= ReadFile( handle
, &hdr
, cert_hdr_size
, &count
, NULL
);
516 if( count
!= cert_hdr_size
)
519 TRACE("Size = %08lx id = %08hx\n",
520 hdr
.dwLength
, hdr
.wCertificateType
);
522 /* check the certificate is not too big or too small */
523 if( hdr
.dwLength
< cert_hdr_size
)
525 if( hdr
.dwLength
> (size
-offset
) )
528 if( (TypeFilter
== CERT_SECTION_TYPE_ANY
) ||
529 (TypeFilter
== hdr
.wCertificateType
) )
531 (*CertificateCount
)++;
532 if(Indices
&& *CertificateCount
<= IndexCount
)
536 /* next certificate */
537 offset
+= hdr
.dwLength
;
539 /* padded out to the nearest 8-byte boundary */
540 if (hdr
.dwLength
% 8)
541 offset
+= 8 - (hdr
.dwLength
% 8);
549 /***********************************************************************
550 * ImageGetCertificateData (IMAGEHLP.@)
552 * FIXME: not sure that I'm dealing with the Index the right way
554 BOOL WINAPI
ImageGetCertificateData(
555 HANDLE handle
, DWORD Index
,
556 LPWIN_CERTIFICATE Certificate
, PDWORD RequiredLength
)
558 DWORD r
, offset
, ofs
, size
, count
;
560 TRACE("%p %ld %p %p\n", handle
, Index
, Certificate
, RequiredLength
);
564 SetLastError( ERROR_INVALID_PARAMETER
);
568 if( !IMAGEHLP_GetCertificateOffset( handle
, Index
, &ofs
, &size
) )
571 if( *RequiredLength
< size
)
573 *RequiredLength
= size
;
574 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
580 SetLastError( ERROR_INVALID_PARAMETER
);
584 *RequiredLength
= size
;
586 offset
= SetFilePointer( handle
, ofs
, NULL
, FILE_BEGIN
);
587 if( offset
== INVALID_SET_FILE_POINTER
)
590 r
= ReadFile( handle
, Certificate
, size
, &count
, NULL
);
597 SetLastError( NO_ERROR
);
602 /***********************************************************************
603 * ImageGetCertificateHeader (IMAGEHLP.@)
605 BOOL WINAPI
ImageGetCertificateHeader(
606 HANDLE handle
, DWORD index
, LPWIN_CERTIFICATE pCert
)
608 DWORD r
, offset
, ofs
, size
, count
;
609 const size_t cert_hdr_size
= sizeof *pCert
- sizeof pCert
->bCertificate
;
611 TRACE("%p %ld %p\n", handle
, index
, pCert
);
613 if( !IMAGEHLP_GetCertificateOffset( handle
, index
, &ofs
, &size
) )
616 if( size
< cert_hdr_size
)
619 offset
= SetFilePointer( handle
, ofs
, NULL
, FILE_BEGIN
);
620 if( offset
== INVALID_SET_FILE_POINTER
)
623 r
= ReadFile( handle
, pCert
, cert_hdr_size
, &count
, NULL
);
626 if( count
!= cert_hdr_size
)
634 /* Finds the section named section in the array of IMAGE_SECTION_HEADERs hdr. If
635 * found, returns the offset to the section. Otherwise returns 0. If the section
636 * is found, optionally returns the size of the section (in size) and the base
637 * address of the section (in base.)
639 static DWORD
IMAGEHLP_GetSectionOffset( IMAGE_SECTION_HEADER
*hdr
,
640 DWORD num_sections
, LPCSTR section
, PDWORD size
, PDWORD base
)
644 for( i
= 0; !offset
&& i
< num_sections
; i
++, hdr
++ )
646 if( !memcmp( hdr
->Name
, section
, strlen(section
) ) )
648 offset
= hdr
->PointerToRawData
;
650 *size
= hdr
->SizeOfRawData
;
652 *base
= hdr
->VirtualAddress
;
658 /* Calls DigestFunction e bytes at offset offset from the file mapped at map.
659 * Returns the return value of DigestFunction, or FALSE if the data is not available.
661 static BOOL
IMAGEHLP_ReportSectionFromOffset( DWORD offset
, DWORD size
,
662 BYTE
*map
, DWORD fileSize
, DIGEST_FUNCTION DigestFunction
, DIGEST_HANDLE DigestHandle
)
664 if( offset
+ size
> fileSize
)
666 SetLastError(ERROR_INVALID_PARAMETER
);
669 return DigestFunction( DigestHandle
, map
+ offset
, size
);
672 /* Finds the section named section among the IMAGE_SECTION_HEADERs in
673 * section_headers and calls DigestFunction for this section. Returns
674 * the return value from DigestFunction, or FALSE if the data could not be read.
676 static BOOL
IMAGEHLP_ReportSection( IMAGE_SECTION_HEADER
*section_headers
,
677 DWORD num_sections
, LPCSTR section
, BYTE
*map
, DWORD fileSize
,
678 DIGEST_FUNCTION DigestFunction
, DIGEST_HANDLE DigestHandle
)
680 DWORD offset
, size
= 0;
682 offset
= IMAGEHLP_GetSectionOffset( section_headers
, num_sections
, section
,
686 return IMAGEHLP_ReportSectionFromOffset( offset
, size
, map
, fileSize
,
687 DigestFunction
, DigestHandle
);
690 /* Calls DigestFunction for all sections with the IMAGE_SCN_CNT_CODE flag set.
691 * Returns the return value from * DigestFunction, or FALSE if a section could not be read.
693 static BOOL
IMAGEHLP_ReportCodeSections( IMAGE_SECTION_HEADER
*hdr
, DWORD num_sections
,
694 BYTE
*map
, DWORD fileSize
, DIGEST_FUNCTION DigestFunction
, DIGEST_HANDLE DigestHandle
)
699 for( i
= 0; ret
&& i
< num_sections
; i
++, hdr
++ )
701 if( hdr
->Characteristics
& IMAGE_SCN_CNT_CODE
)
702 ret
= IMAGEHLP_ReportSectionFromOffset( hdr
->PointerToRawData
,
703 hdr
->SizeOfRawData
, map
, fileSize
, DigestFunction
, DigestHandle
);
708 /* Reports the import section from the file FileHandle. If
709 * CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO is set in DigestLevel, reports the entire
711 * FIXME: if it's not set, the function currently fails.
713 static BOOL
IMAGEHLP_ReportImportSection( IMAGE_SECTION_HEADER
*hdr
,
714 DWORD num_sections
, BYTE
*map
, DWORD fileSize
, DWORD DigestLevel
,
715 DIGEST_FUNCTION DigestFunction
, DIGEST_HANDLE DigestHandle
)
718 DWORD offset
, size
, base
;
720 /* Get import data */
721 offset
= IMAGEHLP_GetSectionOffset( hdr
, num_sections
, ".idata", &size
,
726 /* If CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO is set, the entire
727 * section is reported. Otherwise, the debug info section is
728 * decoded and reported piecemeal. See tests. However, I haven't been
729 * able to figure out how the native implementation decides which values
730 * to report. Either it's buggy or my understanding is flawed.
732 if( DigestLevel
& CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO
)
733 ret
= IMAGEHLP_ReportSectionFromOffset( offset
, size
, map
, fileSize
,
734 DigestFunction
, DigestHandle
);
737 FIXME("not supported except for CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO\n");
738 SetLastError(ERROR_INVALID_PARAMETER
);
745 /***********************************************************************
746 * ImageGetDigestStream (IMAGEHLP.@)
748 * Gets a stream of bytes from a PE file over which a hash might be computed to
749 * verify that the image has not changed. Useful for creating a certificate to
750 * be added to the file with ImageAddCertificate.
753 * FileHandle [In] File for which to return a stream.
754 * DigestLevel [In] Flags to control which portions of the file to return.
755 * 0 is allowed, as is any combination of:
756 * CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO: reports the entire
757 * import section rather than selected portions of it.
758 * CERT_PE_IMAGE_DIGEST_DEBUG_INFO: reports the debug section.
759 * CERT_PE_IMAGE_DIGEST_RESOURCES: reports the resources
761 * DigestFunction [In] Callback function.
762 * DigestHandle [In] Handle passed as first parameter to DigestFunction.
765 * TRUE if successful.
766 * FALSE if unsuccessful. GetLastError returns more about the error.
769 * Only supports 32-bit PE files, not tested with any other format.
770 * Reports data in the following order:
771 * 1. The file headers are reported first
772 * 2. Any code sections are reported next.
773 * 3. The data (".data" and ".rdata") sections are reported next.
774 * 4. The import section is reported next.
775 * 5. If CERT_PE_IMAGE_DIGEST_DEBUG_INFO is set in DigestLevel, the debug section is
777 * 6. If CERT_PE_IMAGE_DIGEST_RESOURCES is set in DigestLevel, the resources section
781 * CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO must be specified, returns an error if not.
783 BOOL WINAPI
ImageGetDigestStream(
784 HANDLE FileHandle
, DWORD DigestLevel
,
785 DIGEST_FUNCTION DigestFunction
, DIGEST_HANDLE DigestHandle
)
789 DWORD offset
, size
, num_sections
, fileSize
;
790 HANDLE hMap
= INVALID_HANDLE_VALUE
;
792 IMAGE_DOS_HEADER
*dos_hdr
;
793 IMAGE_NT_HEADERS
*nt_hdr
;
794 IMAGE_SECTION_HEADER
*section_headers
;
796 TRACE("(%p, %ld, %p, %p)\n", FileHandle
, DigestLevel
, DigestFunction
,
799 /* Get the file size */
801 goto invalid_parameter
;
802 fileSize
= GetFileSize( FileHandle
, NULL
);
803 if(fileSize
== INVALID_FILE_SIZE
)
804 goto invalid_parameter
;
807 hMap
= CreateFileMappingW( FileHandle
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
808 if( hMap
== INVALID_HANDLE_VALUE
)
809 goto invalid_parameter
;
810 map
= MapViewOfFile( hMap
, FILE_MAP_COPY
, 0, 0, 0 );
812 goto invalid_parameter
;
814 /* Read the file header */
815 if( fileSize
< sizeof(IMAGE_DOS_HEADER
) )
816 goto invalid_parameter
;
817 dos_hdr
= (IMAGE_DOS_HEADER
*)map
;
819 if( dos_hdr
->e_magic
!= IMAGE_DOS_SIGNATURE
)
820 goto invalid_parameter
;
821 offset
= dos_hdr
->e_lfanew
;
822 if( !offset
|| offset
> fileSize
)
823 goto invalid_parameter
;
824 ret
= DigestFunction( DigestHandle
, map
, offset
);
828 /* Read the NT header */
829 if( offset
+ sizeof(IMAGE_NT_HEADERS
) > fileSize
)
830 goto invalid_parameter
;
831 nt_hdr
= (IMAGE_NT_HEADERS
*)(map
+ offset
);
832 if( nt_hdr
->Signature
!= IMAGE_NT_SIGNATURE
)
833 goto invalid_parameter
;
834 /* It's clear why the checksum is cleared, but why only these size headers?
836 nt_hdr
->OptionalHeader
.SizeOfInitializedData
= 0;
837 nt_hdr
->OptionalHeader
.SizeOfImage
= 0;
838 nt_hdr
->OptionalHeader
.CheckSum
= 0;
839 size
= sizeof(nt_hdr
->Signature
) + sizeof(nt_hdr
->FileHeader
) +
840 nt_hdr
->FileHeader
.SizeOfOptionalHeader
;
841 ret
= DigestFunction( DigestHandle
, map
+ offset
, size
);
845 /* Read the section headers */
847 num_sections
= nt_hdr
->FileHeader
.NumberOfSections
;
848 size
= num_sections
* sizeof(IMAGE_SECTION_HEADER
);
849 if( offset
+ size
> fileSize
)
850 goto invalid_parameter
;
851 ret
= DigestFunction( DigestHandle
, map
+ offset
, size
);
855 section_headers
= (IMAGE_SECTION_HEADER
*)(map
+ offset
);
856 IMAGEHLP_ReportCodeSections( section_headers
, num_sections
,
857 map
, fileSize
, DigestFunction
, DigestHandle
);
858 IMAGEHLP_ReportSection( section_headers
, num_sections
, ".data",
859 map
, fileSize
, DigestFunction
, DigestHandle
);
860 IMAGEHLP_ReportSection( section_headers
, num_sections
, ".rdata",
861 map
, fileSize
, DigestFunction
, DigestHandle
);
862 IMAGEHLP_ReportImportSection( section_headers
, num_sections
,
863 map
, fileSize
, DigestLevel
, DigestFunction
, DigestHandle
);
864 if( DigestLevel
& CERT_PE_IMAGE_DIGEST_DEBUG_INFO
)
865 IMAGEHLP_ReportSection( section_headers
, num_sections
, ".debug",
866 map
, fileSize
, DigestFunction
, DigestHandle
);
867 if( DigestLevel
& CERT_PE_IMAGE_DIGEST_RESOURCES
)
868 IMAGEHLP_ReportSection( section_headers
, num_sections
, ".rsrc",
869 map
, fileSize
, DigestFunction
, DigestHandle
);
873 UnmapViewOfFile( map
);
874 if( hMap
!= INVALID_HANDLE_VALUE
)
881 error
= ERROR_INVALID_PARAMETER
;
885 /***********************************************************************
886 * ImageRemoveCertificate (IMAGEHLP.@)
888 BOOL WINAPI
ImageRemoveCertificate(HANDLE FileHandle
, DWORD Index
)
890 DWORD size
= 0, count
= 0, sd_VirtualAddr
= 0, offset
= 0;
891 DWORD data_size
= 0, cert_size
= 0, cert_size_padded
= 0, ret
= 0;
895 TRACE("(%p, %ld)\n", FileHandle
, Index
);
897 r
= ImageEnumerateCertificates(FileHandle
, CERT_SECTION_TYPE_ANY
, &count
, NULL
, 0);
899 if ((!r
) || (count
== 0))
902 if ((!IMAGEHLP_GetSecurityDirOffset(FileHandle
, &sd_VirtualAddr
, &size
)) ||
903 (!IMAGEHLP_GetCertificateOffset(FileHandle
, Index
, &offset
, &cert_size
)))
906 /* Ignore any padding we have, too */
908 cert_size_padded
= cert_size
+ (8 - (cert_size
% 8));
910 cert_size_padded
= cert_size
;
912 data_size
= size
- (offset
- sd_VirtualAddr
) - cert_size_padded
;
916 ret
= SetFilePointer(FileHandle
, sd_VirtualAddr
, NULL
, FILE_BEGIN
);
918 if (ret
== INVALID_SET_FILE_POINTER
)
923 cert_data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, data_size
);
928 ret
= SetFilePointer(FileHandle
, offset
+ cert_size_padded
, NULL
, FILE_BEGIN
);
930 if (ret
== INVALID_SET_FILE_POINTER
)
933 /* Read any subsequent certificates */
934 r
= ReadFile(FileHandle
, cert_data
, data_size
, &count
, NULL
);
936 if ((!r
) || (count
!= data_size
))
939 SetFilePointer(FileHandle
, offset
, NULL
, FILE_BEGIN
);
941 /* Write them one index back */
942 r
= WriteFile(FileHandle
, cert_data
, data_size
, &count
, NULL
);
944 if ((!r
) || (count
!= data_size
))
947 HeapFree(GetProcessHeap(), 0, cert_data
);
950 /* If security directory is at end of file, trim the file */
951 if (GetFileSize(FileHandle
, NULL
) == sd_VirtualAddr
+ size
)
952 SetEndOfFile(FileHandle
);
955 r
= IMAGEHLP_SetSecurityDirOffset(FileHandle
, 0, 0);
957 r
= IMAGEHLP_SetSecurityDirOffset(FileHandle
, sd_VirtualAddr
, size
- cert_size_padded
);
962 if (!IMAGEHLP_RecalculateChecksum(FileHandle
))
968 HeapFree(GetProcessHeap(), 0, cert_data
);