/* * 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 #include "windef.h" #include "winbase.h" #include "winerror.h" #include "winreg.h" #include "winternl.h" #include "winnt.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; }