ChangeLog: * Implement imagehlp.ImageGetCertificateData()
Index: dlls/imagehlp/integrity.c =================================================================== RCS file: /home/wine/wine/dlls/imagehlp/integrity.c,v retrieving revision 1.11 diff -u -r1.11 integrity.c --- dlls/imagehlp/integrity.c 5 Sep 2003 23:08:37 -0000 1.11 +++ dlls/imagehlp/integrity.c 16 Sep 2003 14:10:56 -0000 @@ -2,6 +2,7 @@ * 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 @@ -23,11 +24,104 @@ #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 num, + DWORD *pdwOfs, DWORD *pdwSize ) +{ + IMAGE_DOS_HEADER dos_hdr; + IMAGE_NT_HEADERS nt_hdr; + DWORD size, count, offset, len; + 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("len = %lx addr = %lx\n", sd->Size, sd->VirtualAddress); + + offset = 0; + size = sd->Size; + + /* take the n'th certificate */ + while( 1 ) + { + /* read the length of the current certificate */ + count = SetFilePointer( handle, sd->VirtualAddress + 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->VirtualAddress + offset; + *pdwSize = len; + + TRACE("len = %lx addr = %lx\n", len, sd->VirtualAddress + offset); + + return TRUE; +} + + /*********************************************************************** * ImageAddCertificate (IMAGEHLP.@) */ @@ -58,16 +152,48 @@ /*********************************************************************** * ImageGetCertificateData (IMAGEHLP.@) + * + * FIXME: not sure that I'm dealing with the Index the right way */ BOOL WINAPI ImageGetCertificateData( - HANDLE FileHandle, DWORD CertificateIndex, - PWIN_CERTIFICATE Certificate, PDWORD RequiredLength) + HANDLE handle, DWORD Index, + PWIN_CERTIFICATE Certificate, PDWORD RequiredLength) { - FIXME("(%p, %ld, %p, %p): stub\n", - FileHandle, CertificateIndex, Certificate, RequiredLength - ); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + DWORD r, offset, ofs, size, count; + + TRACE("%p %ld %p %p\n", handle, Index, Certificate, RequiredLength); + + if( !IMAGEHLP_GetSecurityDirOffset( 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; } /***********************************************************************