wintrust: Implement WintrustLoadFunctionPointers.
[wine] / dlls / imagehlp / integrity.c
1 /*
2  *      IMAGEHLP library
3  *
4  *      Copyright 1998  Patrik Stridvall
5  *      Copyright 2003  Mike McCormack
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdarg.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winerror.h"
27 #include "winreg.h"
28 #include "winternl.h"
29 #include "winnt.h"
30 #include "imagehlp.h"
31 #include "wine/debug.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(imagehlp);
34
35 /*
36  * These functions are partially documented at:
37  *   http://www.cs.auckland.ac.nz/~pgut001/pubs/authenticode.txt
38  */
39
40 /***********************************************************************
41  * IMAGEHLP_GetSecurityDirOffset (INTERNAL)
42  *
43  * Read a file's PE header, and return the offset and size of the 
44  *  security directory.
45  */
46 static BOOL IMAGEHLP_GetSecurityDirOffset( HANDLE handle, 
47                                            DWORD *pdwOfs, DWORD *pdwSize )
48 {
49     IMAGE_DOS_HEADER dos_hdr;
50     IMAGE_NT_HEADERS nt_hdr;
51     DWORD count;
52     BOOL r;
53     IMAGE_DATA_DIRECTORY *sd;
54
55     TRACE("handle %p\n", handle );
56
57     /* read the DOS header */
58     count = SetFilePointer( handle, 0, NULL, FILE_BEGIN );
59     if( count == INVALID_SET_FILE_POINTER )
60         return FALSE;
61     count = 0;
62     r = ReadFile( handle, &dos_hdr, sizeof dos_hdr, &count, NULL );
63     if( !r )
64         return FALSE;
65     if( count != sizeof dos_hdr )
66         return FALSE;
67
68     /* read the PE header */
69     count = SetFilePointer( handle, dos_hdr.e_lfanew, NULL, FILE_BEGIN );
70     if( count == INVALID_SET_FILE_POINTER )
71         return FALSE;
72     count = 0;
73     r = ReadFile( handle, &nt_hdr, sizeof nt_hdr, &count, NULL );
74     if( !r )
75         return FALSE;
76     if( count != sizeof nt_hdr )
77         return FALSE;
78
79     sd = &nt_hdr.OptionalHeader.
80                     DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY];
81
82     TRACE("size = %x addr = %x\n", sd->Size, sd->VirtualAddress);
83     *pdwSize = sd->Size;
84     *pdwOfs = sd->VirtualAddress;
85
86     return TRUE;
87 }
88
89 /***********************************************************************
90  * IMAGEHLP_GetCertificateOffset (INTERNAL)
91  *
92  * Read a file's PE header, and return the offset and size of the 
93  *  security directory.
94  */
95 static BOOL IMAGEHLP_GetCertificateOffset( HANDLE handle, DWORD num,
96                                            DWORD *pdwOfs, DWORD *pdwSize )
97 {
98     DWORD size, count, offset, len, sd_VirtualAddr;
99     BOOL r;
100
101     r = IMAGEHLP_GetSecurityDirOffset( handle, &sd_VirtualAddr, &size );
102     if( !r )
103         return FALSE;
104
105     offset = 0;
106     /* take the n'th certificate */
107     while( 1 )
108     {
109         /* read the length of the current certificate */
110         count = SetFilePointer( handle, sd_VirtualAddr + offset,
111                                  NULL, FILE_BEGIN );
112         if( count == INVALID_SET_FILE_POINTER )
113             return FALSE;
114         r = ReadFile( handle, &len, sizeof len, &count, NULL );
115         if( !r )
116             return FALSE;
117         if( count != sizeof len )
118             return FALSE;
119
120         /* check the certificate is not too big or too small */
121         if( len < sizeof len )
122             return FALSE;
123         if( len > (size-offset) )
124             return FALSE;
125         if( !num-- )
126             break;
127
128         /* calculate the offset of the next certificate */
129         offset += len;
130         if( offset >= size )
131             return FALSE;
132     }
133
134     *pdwOfs = sd_VirtualAddr + offset;
135     *pdwSize = len;
136
137     TRACE("len = %x addr = %x\n", len, sd_VirtualAddr + offset);
138
139     return TRUE;
140 }
141
142
143 /***********************************************************************
144  *              ImageAddCertificate (IMAGEHLP.@)
145  */
146
147 BOOL WINAPI ImageAddCertificate(
148   HANDLE FileHandle, PWIN_CERTIFICATE Certificate, PDWORD Index)
149 {
150   FIXME("(%p, %p, %p): stub\n",
151     FileHandle, Certificate, Index
152   );
153   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
154   return FALSE;
155 }
156
157 /***********************************************************************
158  *              ImageEnumerateCertificates (IMAGEHLP.@)
159  */
160 BOOL WINAPI ImageEnumerateCertificates(
161     HANDLE handle, WORD TypeFilter, PDWORD CertificateCount,
162     PDWORD Indices, DWORD IndexCount)
163 {
164     DWORD size, count, offset, sd_VirtualAddr, index;
165     WIN_CERTIFICATE hdr;
166     const size_t cert_hdr_size = sizeof hdr - sizeof hdr.bCertificate;
167     BOOL r;
168
169     TRACE("%p %hd %p %p %d\n",
170            handle, TypeFilter, CertificateCount, Indices, IndexCount);
171
172     r = IMAGEHLP_GetSecurityDirOffset( handle, &sd_VirtualAddr, &size );
173     if( !r )
174         return FALSE;
175
176     offset = 0;
177     index = 0;
178     *CertificateCount = 0;
179     while( offset < size )
180     {
181         /* read the length of the current certificate */
182         count = SetFilePointer( handle, sd_VirtualAddr + offset,
183                                  NULL, FILE_BEGIN );
184         if( count == INVALID_SET_FILE_POINTER )
185             return FALSE;
186         r = ReadFile( handle, &hdr, cert_hdr_size, &count, NULL );
187         if( !r )
188             return FALSE;
189         if( count != cert_hdr_size )
190             return FALSE;
191
192         TRACE("Size = %08x  id = %08hx\n",
193                hdr.dwLength, hdr.wCertificateType );
194
195         /* check the certificate is not too big or too small */
196         if( hdr.dwLength < cert_hdr_size )
197             return FALSE;
198         if( hdr.dwLength > (size-offset) )
199             return FALSE;
200        
201         if( (TypeFilter == CERT_SECTION_TYPE_ANY) ||
202             (TypeFilter == hdr.wCertificateType) )
203         {
204             (*CertificateCount)++;
205             if(Indices && *CertificateCount <= IndexCount)
206                 *Indices++ = index;
207         }
208
209         /* next certificate */
210         offset += hdr.dwLength;
211         index++;
212     }
213
214     return TRUE;
215 }
216
217 /***********************************************************************
218  *              ImageGetCertificateData (IMAGEHLP.@)
219  *
220  *  FIXME: not sure that I'm dealing with the Index the right way
221  */
222 BOOL WINAPI ImageGetCertificateData(
223                 HANDLE handle, DWORD Index,
224                 PWIN_CERTIFICATE Certificate, PDWORD RequiredLength)
225 {
226     DWORD r, offset, ofs, size, count;
227
228     TRACE("%p %d %p %p\n", handle, Index, Certificate, RequiredLength);
229
230     if( !IMAGEHLP_GetCertificateOffset( handle, Index, &ofs, &size ) )
231         return FALSE;
232
233     if( !Certificate )
234     {
235         *RequiredLength = size;
236         return TRUE;
237     }
238
239     if( *RequiredLength < size )
240     {
241         *RequiredLength = size;
242         SetLastError( ERROR_INSUFFICIENT_BUFFER );
243         return FALSE;
244     }
245
246     *RequiredLength = size;
247
248     offset = SetFilePointer( handle, ofs, NULL, FILE_BEGIN );
249     if( offset == INVALID_SET_FILE_POINTER )
250         return FALSE;
251
252     r = ReadFile( handle, Certificate, size, &count, NULL );
253     if( !r )
254         return FALSE;
255     if( count != size )
256         return FALSE;
257
258     TRACE("OK\n");
259
260     return TRUE;
261 }
262
263 /***********************************************************************
264  *              ImageGetCertificateHeader (IMAGEHLP.@)
265  */
266 BOOL WINAPI ImageGetCertificateHeader(
267     HANDLE handle, DWORD index, PWIN_CERTIFICATE pCert)
268 {
269     DWORD r, offset, ofs, size, count;
270     const size_t cert_hdr_size = sizeof *pCert - sizeof pCert->bCertificate;
271
272     TRACE("%p %d %p\n", handle, index, pCert);
273
274     if( !IMAGEHLP_GetCertificateOffset( handle, index, &ofs, &size ) )
275         return FALSE;
276
277     if( size < cert_hdr_size )
278         return FALSE;
279
280     offset = SetFilePointer( handle, ofs, NULL, FILE_BEGIN );
281     if( offset == INVALID_SET_FILE_POINTER )
282         return FALSE;
283
284     r = ReadFile( handle, pCert, cert_hdr_size, &count, NULL );
285     if( !r )
286         return FALSE;
287     if( count != cert_hdr_size )
288         return FALSE;
289
290     TRACE("OK\n");
291
292     return TRUE;
293 }
294
295 /***********************************************************************
296  *              ImageGetDigestStream (IMAGEHLP.@)
297  */
298 BOOL WINAPI ImageGetDigestStream(
299   HANDLE FileHandle, DWORD DigestLevel,
300   DIGEST_FUNCTION DigestFunction, DIGEST_HANDLE DigestHandle)
301 {
302   FIXME("(%p, %d, %p, %p): stub\n",
303     FileHandle, DigestLevel, DigestFunction, DigestHandle
304   );
305   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
306   return FALSE;
307 }
308
309 /***********************************************************************
310  *              ImageRemoveCertificate (IMAGEHLP.@)
311  */
312 BOOL WINAPI ImageRemoveCertificate(HANDLE FileHandle, DWORD Index)
313 {
314   FIXME("(%p, %d): stub\n", FileHandle, Index);
315   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
316   return FALSE;
317 }