msvcrt: Remove strange condition which might lead to crash.
[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, LPWIN_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                 LPWIN_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( !RequiredLength)
230     {
231         SetLastError( ERROR_INVALID_PARAMETER );
232         return FALSE;
233     }
234
235     if( !IMAGEHLP_GetCertificateOffset( handle, Index, &ofs, &size ) )
236         return FALSE;
237
238     if( *RequiredLength < size )
239     {
240         *RequiredLength = size;
241         SetLastError( ERROR_INSUFFICIENT_BUFFER );
242         return FALSE;
243     }
244
245     if( !Certificate )
246     {
247         SetLastError( ERROR_INVALID_PARAMETER );
248         return FALSE;
249     }
250
251     *RequiredLength = size;
252
253     offset = SetFilePointer( handle, ofs, NULL, FILE_BEGIN );
254     if( offset == INVALID_SET_FILE_POINTER )
255         return FALSE;
256
257     r = ReadFile( handle, Certificate, size, &count, NULL );
258     if( !r )
259         return FALSE;
260     if( count != size )
261         return FALSE;
262
263     TRACE("OK\n");
264     SetLastError( NO_ERROR );
265
266     return TRUE;
267 }
268
269 /***********************************************************************
270  *              ImageGetCertificateHeader (IMAGEHLP.@)
271  */
272 BOOL WINAPI ImageGetCertificateHeader(
273     HANDLE handle, DWORD index, LPWIN_CERTIFICATE pCert)
274 {
275     DWORD r, offset, ofs, size, count;
276     const size_t cert_hdr_size = sizeof *pCert - sizeof pCert->bCertificate;
277
278     TRACE("%p %d %p\n", handle, index, pCert);
279
280     if( !IMAGEHLP_GetCertificateOffset( handle, index, &ofs, &size ) )
281         return FALSE;
282
283     if( size < cert_hdr_size )
284         return FALSE;
285
286     offset = SetFilePointer( handle, ofs, NULL, FILE_BEGIN );
287     if( offset == INVALID_SET_FILE_POINTER )
288         return FALSE;
289
290     r = ReadFile( handle, pCert, cert_hdr_size, &count, NULL );
291     if( !r )
292         return FALSE;
293     if( count != cert_hdr_size )
294         return FALSE;
295
296     TRACE("OK\n");
297
298     return TRUE;
299 }
300
301 /***********************************************************************
302  *              ImageGetDigestStream (IMAGEHLP.@)
303  */
304 BOOL WINAPI ImageGetDigestStream(
305   HANDLE FileHandle, DWORD DigestLevel,
306   DIGEST_FUNCTION DigestFunction, DIGEST_HANDLE DigestHandle)
307 {
308   FIXME("(%p, %d, %p, %p): stub\n",
309     FileHandle, DigestLevel, DigestFunction, DigestHandle
310   );
311   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
312   return FALSE;
313 }
314
315 /***********************************************************************
316  *              ImageRemoveCertificate (IMAGEHLP.@)
317  */
318 BOOL WINAPI ImageRemoveCertificate(HANDLE FileHandle, DWORD Index)
319 {
320   FIXME("(%p, %d): stub\n", FileHandle, Index);
321   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
322   return FALSE;
323 }