| /* | |
| * IMAGEHLP library | |
| * | |
| * Copyright 1998 Patrik Stridvall | |
| * Copyright 2003 Mike McCormack | |
| * | |
| * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| */ | |
| #include <stdarg.h> | |
| #include "windef.h" | |
| #include "winbase.h" | |
| #include "winerror.h" | |
| #include "winreg.h" | |
| #include "winternl.h" | |
| #include "winnt.h" | |
| #include "ntstatus.h" | |
| #include "imagehlp.h" | |
| #include "wine/debug.h" | |
| WINE_DEFAULT_DEBUG_CHANNEL(imagehlp); | |
| /* | |
| * These functions are partially documented at: | |
| * http://www.cs.auckland.ac.nz/~pgut001/pubs/authenticode.txt | |
| */ | |
| /*********************************************************************** | |
| * IMAGEHLP_GetSecurityDirOffset (INTERNAL) | |
| * | |
| * Read a file's PE header, and return the offset and size of the | |
| * security directory. | |
| */ | |
| static BOOL IMAGEHLP_GetSecurityDirOffset( HANDLE handle, | |
| DWORD *pdwOfs, DWORD *pdwSize ) | |
| { | |
| IMAGE_DOS_HEADER dos_hdr; | |
| IMAGE_NT_HEADERS nt_hdr; | |
| DWORD count; | |
| BOOL r; | |
| IMAGE_DATA_DIRECTORY *sd; | |
| TRACE("handle %p\n", handle ); | |
| /* read the DOS header */ | |
| count = SetFilePointer( handle, 0, NULL, FILE_BEGIN ); | |
| if( count == INVALID_SET_FILE_POINTER ) | |
| return FALSE; | |
| count = 0; | |
| r = ReadFile( handle, &dos_hdr, sizeof dos_hdr, &count, NULL ); | |
| if( !r ) | |
| return FALSE; | |
| if( count != sizeof dos_hdr ) | |
| return FALSE; | |
| /* read the PE header */ | |
| count = SetFilePointer( handle, dos_hdr.e_lfanew, NULL, FILE_BEGIN ); | |
| if( count == INVALID_SET_FILE_POINTER ) | |
| return FALSE; | |
| count = 0; | |
| r = ReadFile( handle, &nt_hdr, sizeof nt_hdr, &count, NULL ); | |
| if( !r ) | |
| return FALSE; | |
| if( count != sizeof nt_hdr ) | |
| return FALSE; | |
| sd = &nt_hdr.OptionalHeader. | |
| DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY]; | |
| TRACE("size = %lx addr = %lx\n", sd->Size, sd->VirtualAddress); | |
| *pdwSize = sd->Size; | |
| *pdwOfs = sd->VirtualAddress; | |
| return TRUE; | |
| } | |
| /*********************************************************************** | |
| * IMAGEHLP_GetCertificateOffset (INTERNAL) | |
| * | |
| * Read a file's PE header, and return the offset and size of the | |
| * security directory. | |
| */ | |
| static BOOL IMAGEHLP_GetCertificateOffset( HANDLE handle, DWORD num, | |
| DWORD *pdwOfs, DWORD *pdwSize ) | |
| { | |
| DWORD size, count, offset, len, sd_VirtualAddr; | |
| BOOL r; | |
| r = IMAGEHLP_GetSecurityDirOffset( handle, &sd_VirtualAddr, &size ); | |
| if( !r ) | |
| return FALSE; | |
| offset = 0; | |
| /* take the n'th certificate */ | |
| while( 1 ) | |
| { | |
| /* read the length of the current certificate */ | |
| count = SetFilePointer( handle, sd_VirtualAddr + offset, | |
| NULL, FILE_BEGIN ); | |
| if( count == INVALID_SET_FILE_POINTER ) | |
| return FALSE; | |
| r = ReadFile( handle, &len, sizeof len, &count, NULL ); | |
| if( !r ) | |
| return FALSE; | |
| if( count != sizeof len ) | |
| return FALSE; | |
| /* check the certificate is not too big or too small */ | |
| if( len < sizeof len ) | |
| return FALSE; | |
| if( len > (size-offset) ) | |
| return FALSE; | |
| if( !num-- ) | |
| break; | |
| /* calculate the offset of the next certificate */ | |
| offset += len; | |
| if( offset >= size ) | |
| return FALSE; | |
| } | |
| *pdwOfs = sd_VirtualAddr + offset; | |
| *pdwSize = len; | |
| TRACE("len = %lx addr = %lx\n", len, sd_VirtualAddr + offset); | |
| return TRUE; | |
| } | |
| /*********************************************************************** | |
| * ImageAddCertificate (IMAGEHLP.@) | |
| */ | |
| BOOL WINAPI ImageAddCertificate( | |
| HANDLE FileHandle, PWIN_CERTIFICATE Certificate, PDWORD Index) | |
| { | |
| FIXME("(%p, %p, %p): stub\n", | |
| FileHandle, Certificate, Index | |
| ); | |
| SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | |
| return FALSE; | |
| } | |
| /*********************************************************************** | |
| * ImageEnumerateCertificates (IMAGEHLP.@) | |
| */ | |
| BOOL WINAPI ImageEnumerateCertificates( | |
| HANDLE handle, WORD TypeFilter, PDWORD CertificateCount, | |
| PDWORD Indices, DWORD IndexCount) | |
| { | |
| DWORD size, count, offset, sd_VirtualAddr; | |
| WIN_CERTIFICATE hdr; | |
| const size_t cert_hdr_size = sizeof hdr - sizeof hdr.bCertificate; | |
| BOOL r; | |
| TRACE("%p %hd %p %p %ld\n", | |
| handle, TypeFilter, CertificateCount, Indices, IndexCount); | |
| if( Indices ) | |
| { | |
| FIXME("Indicies not handled!\n"); | |
| return FALSE; | |
| } | |
| r = IMAGEHLP_GetSecurityDirOffset( handle, &sd_VirtualAddr, &size ); | |
| if( !r ) | |
| return FALSE; | |
| offset = 0; | |
| *CertificateCount = 0; | |
| while( offset < size ) | |
| { | |
| /* read the length of the current certificate */ | |
| count = SetFilePointer( handle, sd_VirtualAddr + offset, | |
| NULL, FILE_BEGIN ); | |
| if( count == INVALID_SET_FILE_POINTER ) | |
| return FALSE; | |
| r = ReadFile( handle, &hdr, cert_hdr_size, &count, NULL ); | |
| if( !r ) | |
| return FALSE; | |
| if( count != cert_hdr_size ) | |
| return FALSE; | |
| TRACE("Size = %08lx id = %08hx\n", | |
| hdr.dwLength, hdr.wCertificateType ); | |
| /* check the certificate is not too big or too small */ | |
| if( hdr.dwLength < cert_hdr_size ) | |
| return FALSE; | |
| if( hdr.dwLength > (size-offset) ) | |
| return FALSE; | |
| if( (TypeFilter == CERT_SECTION_TYPE_ANY) || | |
| (TypeFilter == hdr.wCertificateType) ) | |
| { | |
| (*CertificateCount)++; | |
| } | |
| /* next certificate */ | |
| offset += hdr.dwLength; | |
| } | |
| return TRUE; | |
| } | |
| /*********************************************************************** | |
| * ImageGetCertificateData (IMAGEHLP.@) | |
| * | |
| * FIXME: not sure that I'm dealing with the Index the right way | |
| */ | |
| BOOL WINAPI ImageGetCertificateData( | |
| HANDLE handle, DWORD Index, | |
| PWIN_CERTIFICATE Certificate, PDWORD RequiredLength) | |
| { | |
| DWORD r, offset, ofs, size, count; | |
| TRACE("%p %ld %p %p\n", handle, Index, Certificate, RequiredLength); | |
| if( !IMAGEHLP_GetCertificateOffset( handle, Index, &ofs, &size ) ) | |
| return FALSE; | |
| if( !Certificate ) | |
| { | |
| *RequiredLength = size; | |
| return TRUE; | |
| } | |
| if( *RequiredLength < size ) | |
| { | |
| *RequiredLength = size; | |
| SetLastError( ERROR_INSUFFICIENT_BUFFER ); | |
| return FALSE; | |
| } | |
| *RequiredLength = size; | |
| offset = SetFilePointer( handle, ofs, NULL, FILE_BEGIN ); | |
| if( offset == INVALID_SET_FILE_POINTER ) | |
| return FALSE; | |
| r = ReadFile( handle, Certificate, size, &count, NULL ); | |
| if( !r ) | |
| return FALSE; | |
| if( count != size ) | |
| return FALSE; | |
| TRACE("OK\n"); | |
| return TRUE; | |
| } | |
| /*********************************************************************** | |
| * ImageGetCertificateHeader (IMAGEHLP.@) | |
| */ | |
| BOOL WINAPI ImageGetCertificateHeader( | |
| HANDLE handle, DWORD index, PWIN_CERTIFICATE pCert) | |
| { | |
| DWORD r, offset, ofs, size, count; | |
| const size_t cert_hdr_size = sizeof *pCert - sizeof pCert->bCertificate; | |
| TRACE("%p %ld %p\n", handle, index, pCert); | |
| if( !IMAGEHLP_GetCertificateOffset( handle, index, &ofs, &size ) ) | |
| return FALSE; | |
| if( size < cert_hdr_size ) | |
| return FALSE; | |
| offset = SetFilePointer( handle, ofs, NULL, FILE_BEGIN ); | |
| if( offset == INVALID_SET_FILE_POINTER ) | |
| return FALSE; | |
| r = ReadFile( handle, pCert, cert_hdr_size, &count, NULL ); | |
| if( !r ) | |
| return FALSE; | |
| if( count != cert_hdr_size ) | |
| return FALSE; | |
| TRACE("OK\n"); | |
| return TRUE; | |
| } | |
| /*********************************************************************** | |
| * ImageGetDigestStream (IMAGEHLP.@) | |
| */ | |
| BOOL WINAPI ImageGetDigestStream( | |
| HANDLE FileHandle, DWORD DigestLevel, | |
| DIGEST_FUNCTION DigestFunction, DIGEST_HANDLE DigestHandle) | |
| { | |
| FIXME("(%p, %ld, %p, %p): stub\n", | |
| FileHandle, DigestLevel, DigestFunction, DigestHandle | |
| ); | |
| SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | |
| return FALSE; | |
| } | |
| /*********************************************************************** | |
| * ImageRemoveCertificate (IMAGEHLP.@) | |
| */ | |
| BOOL WINAPI ImageRemoveCertificate(HANDLE FileHandle, DWORD Index) | |
| { | |
| FIXME("(%p, %ld): stub\n", FileHandle, Index); | |
| SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | |
| return FALSE; | |
| } |