atl: Fix compilation warnings in 64-bit mode.
[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 "winternl.h"
28 #include "winnt.h"
29 #include "imagehlp.h"
30 #include "wine/debug.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(imagehlp);
33
34 /*
35  * These functions are partially documented at:
36  *   http://www.cs.auckland.ac.nz/~pgut001/pubs/authenticode.txt
37  */
38
39 /***********************************************************************
40  * IMAGEHLP_GetSecurityDirOffset (INTERNAL)
41  *
42  * Read a file's PE header, and return the offset and size of the 
43  *  security directory.
44  */
45 static BOOL IMAGEHLP_GetSecurityDirOffset( HANDLE handle, 
46                                            DWORD *pdwOfs, DWORD *pdwSize )
47 {
48     IMAGE_DOS_HEADER dos_hdr;
49     IMAGE_NT_HEADERS nt_hdr;
50     DWORD count;
51     BOOL r;
52     IMAGE_DATA_DIRECTORY *sd;
53
54     TRACE("handle %p\n", handle );
55
56     /* read the DOS header */
57     count = SetFilePointer( handle, 0, NULL, FILE_BEGIN );
58     if( count == INVALID_SET_FILE_POINTER )
59         return FALSE;
60     count = 0;
61     r = ReadFile( handle, &dos_hdr, sizeof dos_hdr, &count, NULL );
62     if( !r )
63         return FALSE;
64     if( count != sizeof dos_hdr )
65         return FALSE;
66
67     /* read the PE header */
68     count = SetFilePointer( handle, dos_hdr.e_lfanew, NULL, FILE_BEGIN );
69     if( count == INVALID_SET_FILE_POINTER )
70         return FALSE;
71     count = 0;
72     r = ReadFile( handle, &nt_hdr, sizeof nt_hdr, &count, NULL );
73     if( !r )
74         return FALSE;
75     if( count != sizeof nt_hdr )
76         return FALSE;
77
78     sd = &nt_hdr.OptionalHeader.
79                     DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY];
80
81     TRACE("size = %x addr = %x\n", sd->Size, sd->VirtualAddress);
82     *pdwSize = sd->Size;
83     *pdwOfs = sd->VirtualAddress;
84
85     return TRUE;
86 }
87
88 /***********************************************************************
89  * IMAGEHLP_GetCertificateOffset (INTERNAL)
90  *
91  * Read a file's PE header, and return the offset and size of the 
92  *  security directory.
93  */
94 static BOOL IMAGEHLP_GetCertificateOffset( HANDLE handle, DWORD num,
95                                            DWORD *pdwOfs, DWORD *pdwSize )
96 {
97     DWORD size, count, offset, len, sd_VirtualAddr;
98     BOOL r;
99
100     r = IMAGEHLP_GetSecurityDirOffset( handle, &sd_VirtualAddr, &size );
101     if( !r )
102         return FALSE;
103
104     offset = 0;
105     /* take the n'th certificate */
106     while( 1 )
107     {
108         /* read the length of the current certificate */
109         count = SetFilePointer( handle, sd_VirtualAddr + offset,
110                                  NULL, FILE_BEGIN );
111         if( count == INVALID_SET_FILE_POINTER )
112             return FALSE;
113         r = ReadFile( handle, &len, sizeof len, &count, NULL );
114         if( !r )
115             return FALSE;
116         if( count != sizeof len )
117             return FALSE;
118
119         /* check the certificate is not too big or too small */
120         if( len < sizeof len )
121             return FALSE;
122         if( len > (size-offset) )
123             return FALSE;
124         if( !num-- )
125             break;
126
127         /* calculate the offset of the next certificate */
128         offset += len;
129         if( offset >= size )
130             return FALSE;
131     }
132
133     *pdwOfs = sd_VirtualAddr + offset;
134     *pdwSize = len;
135
136     TRACE("len = %x addr = %x\n", len, sd_VirtualAddr + offset);
137
138     return TRUE;
139 }
140
141
142 /***********************************************************************
143  *              ImageAddCertificate (IMAGEHLP.@)
144  */
145
146 BOOL WINAPI ImageAddCertificate(
147   HANDLE FileHandle, PWIN_CERTIFICATE Certificate, PDWORD Index)
148 {
149   FIXME("(%p, %p, %p): stub\n",
150     FileHandle, Certificate, Index
151   );
152   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
153   return FALSE;
154 }
155
156 /***********************************************************************
157  *              ImageEnumerateCertificates (IMAGEHLP.@)
158  */
159 BOOL WINAPI ImageEnumerateCertificates(
160     HANDLE handle, WORD TypeFilter, PDWORD CertificateCount,
161     PDWORD Indices, DWORD IndexCount)
162 {
163     DWORD size, count, offset, sd_VirtualAddr, index;
164     WIN_CERTIFICATE hdr;
165     const size_t cert_hdr_size = sizeof hdr - sizeof hdr.bCertificate;
166     BOOL r;
167
168     TRACE("%p %hd %p %p %d\n",
169            handle, TypeFilter, CertificateCount, Indices, IndexCount);
170
171     r = IMAGEHLP_GetSecurityDirOffset( handle, &sd_VirtualAddr, &size );
172     if( !r )
173         return FALSE;
174
175     offset = 0;
176     index = 0;
177     *CertificateCount = 0;
178     while( offset < size )
179     {
180         /* read the length of the current certificate */
181         count = SetFilePointer( handle, sd_VirtualAddr + offset,
182                                  NULL, FILE_BEGIN );
183         if( count == INVALID_SET_FILE_POINTER )
184             return FALSE;
185         r = ReadFile( handle, &hdr, cert_hdr_size, &count, NULL );
186         if( !r )
187             return FALSE;
188         if( count != cert_hdr_size )
189             return FALSE;
190
191         TRACE("Size = %08x  id = %08hx\n",
192                hdr.dwLength, hdr.wCertificateType );
193
194         /* check the certificate is not too big or too small */
195         if( hdr.dwLength < cert_hdr_size )
196             return FALSE;
197         if( hdr.dwLength > (size-offset) )
198             return FALSE;
199        
200         if( (TypeFilter == CERT_SECTION_TYPE_ANY) ||
201             (TypeFilter == hdr.wCertificateType) )
202         {
203             (*CertificateCount)++;
204             if(Indices && *CertificateCount <= IndexCount)
205                 *Indices++ = index;
206         }
207
208         /* next certificate */
209         offset += hdr.dwLength;
210         index++;
211     }
212
213     return TRUE;
214 }
215
216 /***********************************************************************
217  *              ImageGetCertificateData (IMAGEHLP.@)
218  *
219  *  FIXME: not sure that I'm dealing with the Index the right way
220  */
221 BOOL WINAPI ImageGetCertificateData(
222                 HANDLE handle, DWORD Index,
223                 PWIN_CERTIFICATE Certificate, PDWORD RequiredLength)
224 {
225     DWORD r, offset, ofs, size, count;
226
227     TRACE("%p %d %p %p\n", handle, Index, Certificate, RequiredLength);
228
229     if( !IMAGEHLP_GetCertificateOffset( handle, Index, &ofs, &size ) )
230         return FALSE;
231
232     if( !Certificate )
233     {
234         *RequiredLength = size;
235         return TRUE;
236     }
237
238     if( *RequiredLength < size )
239     {
240         *RequiredLength = size;
241         SetLastError( ERROR_INSUFFICIENT_BUFFER );
242         return FALSE;
243     }
244
245     *RequiredLength = size;
246
247     offset = SetFilePointer( handle, ofs, NULL, FILE_BEGIN );
248     if( offset == INVALID_SET_FILE_POINTER )
249         return FALSE;
250
251     r = ReadFile( handle, Certificate, size, &count, NULL );
252     if( !r )
253         return FALSE;
254     if( count != size )
255         return FALSE;
256
257     TRACE("OK\n");
258
259     return TRUE;
260 }
261
262 /***********************************************************************
263  *              ImageGetCertificateHeader (IMAGEHLP.@)
264  */
265 BOOL WINAPI ImageGetCertificateHeader(
266     HANDLE handle, DWORD index, PWIN_CERTIFICATE pCert)
267 {
268     DWORD r, offset, ofs, size, count;
269     const size_t cert_hdr_size = sizeof *pCert - sizeof pCert->bCertificate;
270
271     TRACE("%p %d %p\n", handle, index, pCert);
272
273     if( !IMAGEHLP_GetCertificateOffset( handle, index, &ofs, &size ) )
274         return FALSE;
275
276     if( size < cert_hdr_size )
277         return FALSE;
278
279     offset = SetFilePointer( handle, ofs, NULL, FILE_BEGIN );
280     if( offset == INVALID_SET_FILE_POINTER )
281         return FALSE;
282
283     r = ReadFile( handle, pCert, cert_hdr_size, &count, NULL );
284     if( !r )
285         return FALSE;
286     if( count != cert_hdr_size )
287         return FALSE;
288
289     TRACE("OK\n");
290
291     return TRUE;
292 }
293
294 /***********************************************************************
295  *              ImageGetDigestStream (IMAGEHLP.@)
296  */
297 BOOL WINAPI ImageGetDigestStream(
298   HANDLE FileHandle, DWORD DigestLevel,
299   DIGEST_FUNCTION DigestFunction, DIGEST_HANDLE DigestHandle)
300 {
301   FIXME("(%p, %d, %p, %p): stub\n",
302     FileHandle, DigestLevel, DigestFunction, DigestHandle
303   );
304   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
305   return FALSE;
306 }
307
308 /***********************************************************************
309  *              ImageRemoveCertificate (IMAGEHLP.@)
310  */
311 BOOL WINAPI ImageRemoveCertificate(HANDLE FileHandle, DWORD Index)
312 {
313   FIXME("(%p, %d): stub\n", FileHandle, Index);
314   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
315   return FALSE;
316 }