ole32: Add a field to the TLS data to determine whether OLE has been initialised...
[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;
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     if( Indices )
173     {
174         FIXME("Indices not handled!\n");
175         return FALSE;
176     }
177
178     r = IMAGEHLP_GetSecurityDirOffset( handle, &sd_VirtualAddr, &size );
179     if( !r )
180         return FALSE;
181
182     offset = 0;
183     *CertificateCount = 0;
184     while( offset < size )
185     {
186         /* read the length of the current certificate */
187         count = SetFilePointer( handle, sd_VirtualAddr + offset,
188                                  NULL, FILE_BEGIN );
189         if( count == INVALID_SET_FILE_POINTER )
190             return FALSE;
191         r = ReadFile( handle, &hdr, cert_hdr_size, &count, NULL );
192         if( !r )
193             return FALSE;
194         if( count != cert_hdr_size )
195             return FALSE;
196
197         TRACE("Size = %08x  id = %08hx\n",
198                hdr.dwLength, hdr.wCertificateType );
199
200         /* check the certificate is not too big or too small */
201         if( hdr.dwLength < cert_hdr_size )
202             return FALSE;
203         if( hdr.dwLength > (size-offset) )
204             return FALSE;
205        
206         if( (TypeFilter == CERT_SECTION_TYPE_ANY) ||
207             (TypeFilter == hdr.wCertificateType) )
208         {
209             (*CertificateCount)++;
210         }
211
212         /* next certificate */
213         offset += hdr.dwLength;
214     }
215
216     return TRUE;
217 }
218
219 /***********************************************************************
220  *              ImageGetCertificateData (IMAGEHLP.@)
221  *
222  *  FIXME: not sure that I'm dealing with the Index the right way
223  */
224 BOOL WINAPI ImageGetCertificateData(
225                 HANDLE handle, DWORD Index,
226                 PWIN_CERTIFICATE Certificate, PDWORD RequiredLength)
227 {
228     DWORD r, offset, ofs, size, count;
229
230     TRACE("%p %d %p %p\n", handle, Index, Certificate, RequiredLength);
231
232     if( !IMAGEHLP_GetCertificateOffset( handle, Index, &ofs, &size ) )
233         return FALSE;
234
235     if( !Certificate )
236     {
237         *RequiredLength = size;
238         return TRUE;
239     }
240
241     if( *RequiredLength < size )
242     {
243         *RequiredLength = size;
244         SetLastError( ERROR_INSUFFICIENT_BUFFER );
245         return FALSE;
246     }
247
248     *RequiredLength = size;
249
250     offset = SetFilePointer( handle, ofs, NULL, FILE_BEGIN );
251     if( offset == INVALID_SET_FILE_POINTER )
252         return FALSE;
253
254     r = ReadFile( handle, Certificate, size, &count, NULL );
255     if( !r )
256         return FALSE;
257     if( count != size )
258         return FALSE;
259
260     TRACE("OK\n");
261
262     return TRUE;
263 }
264
265 /***********************************************************************
266  *              ImageGetCertificateHeader (IMAGEHLP.@)
267  */
268 BOOL WINAPI ImageGetCertificateHeader(
269     HANDLE handle, DWORD index, PWIN_CERTIFICATE pCert)
270 {
271     DWORD r, offset, ofs, size, count;
272     const size_t cert_hdr_size = sizeof *pCert - sizeof pCert->bCertificate;
273
274     TRACE("%p %d %p\n", handle, index, pCert);
275
276     if( !IMAGEHLP_GetCertificateOffset( handle, index, &ofs, &size ) )
277         return FALSE;
278
279     if( size < cert_hdr_size )
280         return FALSE;
281
282     offset = SetFilePointer( handle, ofs, NULL, FILE_BEGIN );
283     if( offset == INVALID_SET_FILE_POINTER )
284         return FALSE;
285
286     r = ReadFile( handle, pCert, cert_hdr_size, &count, NULL );
287     if( !r )
288         return FALSE;
289     if( count != cert_hdr_size )
290         return FALSE;
291
292     TRACE("OK\n");
293
294     return TRUE;
295 }
296
297 /***********************************************************************
298  *              ImageGetDigestStream (IMAGEHLP.@)
299  */
300 BOOL WINAPI ImageGetDigestStream(
301   HANDLE FileHandle, DWORD DigestLevel,
302   DIGEST_FUNCTION DigestFunction, DIGEST_HANDLE DigestHandle)
303 {
304   FIXME("(%p, %d, %p, %p): stub\n",
305     FileHandle, DigestLevel, DigestFunction, DigestHandle
306   );
307   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
308   return FALSE;
309 }
310
311 /***********************************************************************
312  *              ImageRemoveCertificate (IMAGEHLP.@)
313  */
314 BOOL WINAPI ImageRemoveCertificate(HANDLE FileHandle, DWORD Index)
315 {
316   FIXME("(%p, %d): stub\n", FileHandle, Index);
317   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
318   return FALSE;
319 }