ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

integrity.c
Go to the documentation of this file.
00001 /*
00002  *  IMAGEHLP library
00003  *
00004  *  Copyright 1998  Patrik Stridvall
00005  *  Copyright 2003  Mike McCormack
00006  *  Copyright 2009  Owen Rudge for CodeWeavers
00007  *  Copyright 2010  Juan Lang
00008  *  Copyright 2010  Andrey Turkin
00009  *
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or (at your option) any later version.
00014  *
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00023  */
00024 
00025 #include <stdarg.h>
00026 
00027 #include "windef.h"
00028 #include "winbase.h"
00029 #include "winerror.h"
00030 #include "winternl.h"
00031 #include "winnt.h"
00032 #include "imagehlp.h"
00033 #include "wine/debug.h"
00034 
00035 WINE_DEFAULT_DEBUG_CHANNEL(imagehlp);
00036 
00037 /*
00038  * These functions are partially documented at:
00039  *   http://www.cs.auckland.ac.nz/~pgut001/pubs/authenticode.txt
00040  */
00041 
00042 #define HDR_FAIL   -1
00043 #define HDR_NT32    0
00044 #define HDR_NT64    1
00045 
00046 /***********************************************************************
00047  * IMAGEHLP_GetNTHeaders (INTERNAL)
00048  *
00049  * Return the IMAGE_NT_HEADERS for a PE file, after validating magic
00050  * numbers and distinguishing between 32-bit and 64-bit files.
00051  */
00052 static int IMAGEHLP_GetNTHeaders(HANDLE handle, DWORD *pe_offset, IMAGE_NT_HEADERS32 *nt32, IMAGE_NT_HEADERS64 *nt64)
00053 {
00054     IMAGE_DOS_HEADER dos_hdr;
00055     DWORD count;
00056     BOOL r;
00057 
00058     TRACE("handle %p\n", handle);
00059 
00060     if ((!nt32) || (!nt64))
00061         return HDR_FAIL;
00062 
00063     /* read the DOS header */
00064     count = SetFilePointer(handle, 0, NULL, FILE_BEGIN);
00065 
00066     if (count == INVALID_SET_FILE_POINTER)
00067         return HDR_FAIL;
00068 
00069     count = 0;
00070 
00071     r = ReadFile(handle, &dos_hdr, sizeof dos_hdr, &count, NULL);
00072 
00073     if (!r)
00074         return HDR_FAIL;
00075 
00076     if (count != sizeof dos_hdr)
00077         return HDR_FAIL;
00078 
00079     /* verify magic number of 'MZ' */
00080     if (dos_hdr.e_magic != IMAGE_DOS_SIGNATURE)
00081         return HDR_FAIL;
00082 
00083     if (pe_offset != NULL)
00084         *pe_offset = dos_hdr.e_lfanew;
00085 
00086     /* read the PE header */
00087     count = SetFilePointer(handle, dos_hdr.e_lfanew, NULL, FILE_BEGIN);
00088 
00089     if (count == INVALID_SET_FILE_POINTER)
00090         return HDR_FAIL;
00091 
00092     count = 0;
00093 
00094     r = ReadFile(handle, nt32, sizeof(IMAGE_NT_HEADERS32), &count, NULL);
00095 
00096     if (!r)
00097         return HDR_FAIL;
00098 
00099     if (count != sizeof(IMAGE_NT_HEADERS32))
00100         return HDR_FAIL;
00101 
00102     /* verify NT signature */
00103     if (nt32->Signature != IMAGE_NT_SIGNATURE)
00104         return HDR_FAIL;
00105 
00106     /* check if we have a 32-bit or 64-bit executable */
00107     switch (nt32->OptionalHeader.Magic)
00108     {
00109         case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
00110             return HDR_NT32;
00111 
00112         case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
00113             /* Re-read as 64-bit */
00114 
00115             count = SetFilePointer(handle, dos_hdr.e_lfanew, NULL, FILE_BEGIN);
00116 
00117             if (count == INVALID_SET_FILE_POINTER)
00118                 return HDR_FAIL;
00119 
00120             count = 0;
00121 
00122             r = ReadFile(handle, nt64, sizeof(IMAGE_NT_HEADERS64), &count, NULL);
00123 
00124             if (!r)
00125                 return HDR_FAIL;
00126 
00127             if (count != sizeof(IMAGE_NT_HEADERS64))
00128                 return HDR_FAIL;
00129 
00130             /* verify NT signature */
00131             if (nt64->Signature != IMAGE_NT_SIGNATURE)
00132                 return HDR_FAIL;
00133 
00134             return HDR_NT64;
00135     }
00136 
00137     return HDR_FAIL;
00138 }
00139 
00140 /***********************************************************************
00141  * IMAGEHLP_GetSecurityDirOffset (INTERNAL)
00142  *
00143  * Read a file's PE header, and return the offset and size of the
00144  *  security directory.
00145  */
00146 static BOOL IMAGEHLP_GetSecurityDirOffset( HANDLE handle,
00147                                            DWORD *pdwOfs, DWORD *pdwSize )
00148 {
00149     IMAGE_NT_HEADERS32 nt_hdr32;
00150     IMAGE_NT_HEADERS64 nt_hdr64;
00151     IMAGE_DATA_DIRECTORY *sd;
00152     int ret;
00153 
00154     ret = IMAGEHLP_GetNTHeaders(handle, NULL, &nt_hdr32, &nt_hdr64);
00155 
00156     if (ret == HDR_NT32)
00157         sd = &nt_hdr32.OptionalHeader.DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY];
00158     else if (ret == HDR_NT64)
00159         sd = &nt_hdr64.OptionalHeader.DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY];
00160     else
00161         return FALSE;
00162 
00163     TRACE("ret = %d size = %x addr = %x\n", ret, sd->Size, sd->VirtualAddress);
00164 
00165     *pdwSize = sd->Size;
00166     *pdwOfs = sd->VirtualAddress;
00167 
00168     return TRUE;
00169 }
00170 
00171 /***********************************************************************
00172  * IMAGEHLP_SetSecurityDirOffset (INTERNAL)
00173  *
00174  * Read a file's PE header, and update the offset and size of the
00175  *  security directory.
00176  */
00177 static BOOL IMAGEHLP_SetSecurityDirOffset(HANDLE handle,
00178                                           DWORD dwOfs, DWORD dwSize)
00179 {
00180     IMAGE_NT_HEADERS32 nt_hdr32;
00181     IMAGE_NT_HEADERS64 nt_hdr64;
00182     IMAGE_DATA_DIRECTORY *sd;
00183     int ret, nt_hdr_size = 0;
00184     DWORD pe_offset;
00185     void *nt_hdr;
00186     DWORD count;
00187     BOOL r;
00188 
00189     ret = IMAGEHLP_GetNTHeaders(handle, &pe_offset, &nt_hdr32, &nt_hdr64);
00190 
00191     if (ret == HDR_NT32)
00192     {
00193         sd = &nt_hdr32.OptionalHeader.DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY];
00194 
00195         nt_hdr = &nt_hdr32;
00196         nt_hdr_size = sizeof(IMAGE_NT_HEADERS32);
00197     }
00198     else if (ret == HDR_NT64)
00199     {
00200         sd = &nt_hdr64.OptionalHeader.DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY];
00201 
00202         nt_hdr = &nt_hdr64;
00203         nt_hdr_size = sizeof(IMAGE_NT_HEADERS64);
00204     }
00205     else
00206         return FALSE;
00207 
00208     sd->Size = dwSize;
00209     sd->VirtualAddress = dwOfs;
00210 
00211     TRACE("size = %x addr = %x\n", sd->Size, sd->VirtualAddress);
00212 
00213     /* write the header back again */
00214     count = SetFilePointer(handle, pe_offset, NULL, FILE_BEGIN);
00215 
00216     if (count == INVALID_SET_FILE_POINTER)
00217         return FALSE;
00218 
00219     count = 0;
00220 
00221     r = WriteFile(handle, nt_hdr, nt_hdr_size, &count, NULL);
00222 
00223     if (!r)
00224         return FALSE;
00225 
00226     if (count != nt_hdr_size)
00227         return FALSE;
00228 
00229     return TRUE;
00230 }
00231 
00232 /***********************************************************************
00233  * IMAGEHLP_GetCertificateOffset (INTERNAL)
00234  *
00235  * Read a file's PE header, and return the offset and size of the 
00236  *  security directory.
00237  */
00238 static BOOL IMAGEHLP_GetCertificateOffset( HANDLE handle, DWORD num,
00239                                            DWORD *pdwOfs, DWORD *pdwSize )
00240 {
00241     DWORD size, count, offset, len, sd_VirtualAddr;
00242     BOOL r;
00243 
00244     r = IMAGEHLP_GetSecurityDirOffset( handle, &sd_VirtualAddr, &size );
00245     if( !r )
00246         return FALSE;
00247 
00248     offset = 0;
00249     /* take the n'th certificate */
00250     while( 1 )
00251     {
00252         /* read the length of the current certificate */
00253         count = SetFilePointer( handle, sd_VirtualAddr + offset,
00254                                  NULL, FILE_BEGIN );
00255         if( count == INVALID_SET_FILE_POINTER )
00256             return FALSE;
00257         r = ReadFile( handle, &len, sizeof len, &count, NULL );
00258         if( !r )
00259             return FALSE;
00260         if( count != sizeof len )
00261             return FALSE;
00262 
00263         /* check the certificate is not too big or too small */
00264         if( len < sizeof len )
00265             return FALSE;
00266         if( len > (size-offset) )
00267             return FALSE;
00268         if( !num-- )
00269             break;
00270 
00271         /* calculate the offset of the next certificate */
00272         offset += len;
00273 
00274         /* padded out to the nearest 8-byte boundary */
00275         if( len % 8 )
00276             offset += 8 - (len % 8);
00277 
00278         if( offset >= size )
00279             return FALSE;
00280     }
00281 
00282     *pdwOfs = sd_VirtualAddr + offset;
00283     *pdwSize = len;
00284 
00285     TRACE("len = %x addr = %x\n", len, sd_VirtualAddr + offset);
00286 
00287     return TRUE;
00288 }
00289 
00290 /***********************************************************************
00291  * IMAGEHLP_RecalculateChecksum (INTERNAL)
00292  *
00293  * Update the NT header checksum for the specified file.
00294  */
00295 static BOOL IMAGEHLP_RecalculateChecksum(HANDLE handle)
00296 {
00297     DWORD FileLength, count, HeaderSum, pe_offset, nt_hdr_size;
00298     IMAGE_NT_HEADERS32 nt_hdr32;
00299     IMAGE_NT_HEADERS64 nt_hdr64;
00300     LPVOID BaseAddress;
00301     HANDLE hMapping;
00302     DWORD *CheckSum;
00303     void *nt_hdr;
00304     int ret;
00305     BOOL r;
00306 
00307     TRACE("handle %p\n", handle);
00308 
00309     ret = IMAGEHLP_GetNTHeaders(handle, &pe_offset, &nt_hdr32, &nt_hdr64);
00310 
00311     if (ret == HDR_NT32)
00312     {
00313         CheckSum = &nt_hdr32.OptionalHeader.CheckSum;
00314 
00315         nt_hdr = &nt_hdr32;
00316         nt_hdr_size = sizeof(IMAGE_NT_HEADERS32);
00317     }
00318     else if (ret == HDR_NT64)
00319     {
00320         CheckSum = &nt_hdr64.OptionalHeader.CheckSum;
00321 
00322         nt_hdr = &nt_hdr64;
00323         nt_hdr_size = sizeof(IMAGE_NT_HEADERS64);
00324     }
00325     else
00326         return FALSE;
00327 
00328     hMapping = CreateFileMappingW(handle, NULL, PAGE_READONLY, 0, 0, NULL);
00329 
00330     if (!hMapping)
00331         return FALSE;
00332 
00333     BaseAddress = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
00334 
00335     if (!BaseAddress)
00336     {
00337         CloseHandle(hMapping);
00338         return FALSE;
00339     }
00340 
00341     FileLength = GetFileSize(handle, NULL);
00342 
00343     *CheckSum = 0;
00344     CheckSumMappedFile(BaseAddress, FileLength, &HeaderSum, CheckSum);
00345 
00346     UnmapViewOfFile(BaseAddress);
00347     CloseHandle(hMapping);
00348 
00349     if (*CheckSum)
00350     {
00351         /* write the header back again */
00352         count = SetFilePointer(handle, pe_offset, NULL, FILE_BEGIN);
00353 
00354         if (count == INVALID_SET_FILE_POINTER)
00355             return FALSE;
00356 
00357         count = 0;
00358 
00359         r = WriteFile(handle, nt_hdr, nt_hdr_size, &count, NULL);
00360 
00361         if (!r)
00362             return FALSE;
00363 
00364         if (count != nt_hdr_size)
00365             return FALSE;
00366 
00367         return TRUE;
00368     }
00369 
00370     return FALSE;
00371 }
00372 
00373 /***********************************************************************
00374  *      ImageAddCertificate (IMAGEHLP.@)
00375  *
00376  * Adds the specified certificate to the security directory of
00377  * open PE file.
00378  */
00379 
00380 BOOL WINAPI ImageAddCertificate(
00381   HANDLE FileHandle, LPWIN_CERTIFICATE Certificate, PDWORD Index)
00382 {
00383     DWORD size = 0, count = 0, offset = 0, sd_VirtualAddr = 0, index = 0;
00384     WIN_CERTIFICATE hdr;
00385     const size_t cert_hdr_size = sizeof hdr - sizeof hdr.bCertificate;
00386     BOOL r;
00387 
00388     TRACE("(%p, %p, %p)\n", FileHandle, Certificate, Index);
00389 
00390     r = IMAGEHLP_GetSecurityDirOffset(FileHandle, &sd_VirtualAddr, &size);
00391 
00392     /* If we've already got a security directory, find the end of it */
00393     if ((r) && (sd_VirtualAddr != 0))
00394     {
00395         /* Check if the security directory is at the end of the file.
00396            If not, we should probably relocate it. */
00397         if (GetFileSize(FileHandle, NULL) != sd_VirtualAddr + size)
00398         {
00399             FIXME("Security directory already present but not located at EOF, not adding certificate\n");
00400 
00401             SetLastError(ERROR_NOT_SUPPORTED);
00402             return FALSE;
00403         }
00404 
00405         while (offset < size)
00406         {
00407             /* read the length of the current certificate */
00408             count = SetFilePointer (FileHandle, sd_VirtualAddr + offset,
00409                                      NULL, FILE_BEGIN);
00410 
00411             if (count == INVALID_SET_FILE_POINTER)
00412                 return FALSE;
00413 
00414             r = ReadFile(FileHandle, &hdr, cert_hdr_size, &count, NULL);
00415 
00416             if (!r)
00417                 return FALSE;
00418 
00419             if (count != cert_hdr_size)
00420                 return FALSE;
00421 
00422             /* check the certificate is not too big or too small */
00423             if (hdr.dwLength < cert_hdr_size)
00424                 return FALSE;
00425 
00426             if (hdr.dwLength > (size-offset))
00427                 return FALSE;
00428 
00429             /* next certificate */
00430             offset += hdr.dwLength;
00431 
00432             /* padded out to the nearest 8-byte boundary */
00433             if (hdr.dwLength % 8)
00434                 offset += 8 - (hdr.dwLength % 8);
00435 
00436             index++;
00437         }
00438 
00439         count = SetFilePointer (FileHandle, sd_VirtualAddr + offset, NULL, FILE_BEGIN);
00440 
00441         if (count == INVALID_SET_FILE_POINTER)
00442             return FALSE;
00443     }
00444     else
00445     {
00446         sd_VirtualAddr = SetFilePointer(FileHandle, 0, NULL, FILE_END);
00447 
00448         if (sd_VirtualAddr == INVALID_SET_FILE_POINTER)
00449             return FALSE;
00450     }
00451 
00452     /* Write the certificate to the file */
00453     r = WriteFile(FileHandle, Certificate, Certificate->dwLength, &count, NULL);
00454 
00455     if (!r)
00456         return FALSE;
00457 
00458     /* Pad out if necessary */
00459     if (Certificate->dwLength % 8)
00460     {
00461         char null[8];
00462 
00463         ZeroMemory(null, 8);
00464         WriteFile(FileHandle, null, 8 - (Certificate->dwLength % 8), &count, NULL);
00465 
00466         size += 8 - (Certificate->dwLength % 8);
00467     }
00468 
00469     size += Certificate->dwLength;
00470 
00471     /* Update the security directory offset and size */
00472     if (!IMAGEHLP_SetSecurityDirOffset(FileHandle, sd_VirtualAddr, size))
00473         return FALSE;
00474 
00475     if (!IMAGEHLP_RecalculateChecksum(FileHandle))
00476         return FALSE;
00477 
00478     if(Index)
00479         *Index = index;
00480     return TRUE;
00481 }
00482 
00483 /***********************************************************************
00484  *      ImageEnumerateCertificates (IMAGEHLP.@)
00485  */
00486 BOOL WINAPI ImageEnumerateCertificates(
00487     HANDLE handle, WORD TypeFilter, PDWORD CertificateCount,
00488     PDWORD Indices, DWORD IndexCount)
00489 {
00490     DWORD size, count, offset, sd_VirtualAddr, index;
00491     WIN_CERTIFICATE hdr;
00492     const size_t cert_hdr_size = sizeof hdr - sizeof hdr.bCertificate;
00493     BOOL r;
00494 
00495     TRACE("%p %hd %p %p %d\n",
00496            handle, TypeFilter, CertificateCount, Indices, IndexCount);
00497 
00498     r = IMAGEHLP_GetSecurityDirOffset( handle, &sd_VirtualAddr, &size );
00499     if( !r )
00500         return FALSE;
00501 
00502     offset = 0;
00503     index = 0;
00504     *CertificateCount = 0;
00505     while( offset < size )
00506     {
00507         /* read the length of the current certificate */
00508         count = SetFilePointer( handle, sd_VirtualAddr + offset,
00509                                  NULL, FILE_BEGIN );
00510         if( count == INVALID_SET_FILE_POINTER )
00511             return FALSE;
00512         r = ReadFile( handle, &hdr, cert_hdr_size, &count, NULL );
00513         if( !r )
00514             return FALSE;
00515         if( count != cert_hdr_size )
00516             return FALSE;
00517 
00518         TRACE("Size = %08x  id = %08hx\n",
00519                hdr.dwLength, hdr.wCertificateType );
00520 
00521         /* check the certificate is not too big or too small */
00522         if( hdr.dwLength < cert_hdr_size )
00523             return FALSE;
00524         if( hdr.dwLength > (size-offset) )
00525             return FALSE;
00526        
00527         if( (TypeFilter == CERT_SECTION_TYPE_ANY) ||
00528             (TypeFilter == hdr.wCertificateType) )
00529         {
00530             (*CertificateCount)++;
00531             if(Indices && *CertificateCount <= IndexCount)
00532                 *Indices++ = index;
00533         }
00534 
00535         /* next certificate */
00536         offset += hdr.dwLength;
00537 
00538         /* padded out to the nearest 8-byte boundary */
00539         if (hdr.dwLength % 8)
00540             offset += 8 - (hdr.dwLength % 8);
00541 
00542         index++;
00543     }
00544 
00545     return TRUE;
00546 }
00547 
00548 /***********************************************************************
00549  *      ImageGetCertificateData (IMAGEHLP.@)
00550  *
00551  *  FIXME: not sure that I'm dealing with the Index the right way
00552  */
00553 BOOL WINAPI ImageGetCertificateData(
00554                 HANDLE handle, DWORD Index,
00555                 LPWIN_CERTIFICATE Certificate, PDWORD RequiredLength)
00556 {
00557     DWORD r, offset, ofs, size, count;
00558 
00559     TRACE("%p %d %p %p\n", handle, Index, Certificate, RequiredLength);
00560 
00561     if( !RequiredLength)
00562     {
00563         SetLastError( ERROR_INVALID_PARAMETER );
00564         return FALSE;
00565     }
00566 
00567     if( !IMAGEHLP_GetCertificateOffset( handle, Index, &ofs, &size ) )
00568         return FALSE;
00569 
00570     if( *RequiredLength < size )
00571     {
00572         *RequiredLength = size;
00573         SetLastError( ERROR_INSUFFICIENT_BUFFER );
00574         return FALSE;
00575     }
00576 
00577     if( !Certificate )
00578     {
00579         SetLastError( ERROR_INVALID_PARAMETER );
00580         return FALSE;
00581     }
00582 
00583     *RequiredLength = size;
00584 
00585     offset = SetFilePointer( handle, ofs, NULL, FILE_BEGIN );
00586     if( offset == INVALID_SET_FILE_POINTER )
00587         return FALSE;
00588 
00589     r = ReadFile( handle, Certificate, size, &count, NULL );
00590     if( !r )
00591         return FALSE;
00592     if( count != size )
00593         return FALSE;
00594 
00595     TRACE("OK\n");
00596     SetLastError( NO_ERROR );
00597 
00598     return TRUE;
00599 }
00600 
00601 /***********************************************************************
00602  *      ImageGetCertificateHeader (IMAGEHLP.@)
00603  */
00604 BOOL WINAPI ImageGetCertificateHeader(
00605     HANDLE handle, DWORD index, LPWIN_CERTIFICATE pCert)
00606 {
00607     DWORD r, offset, ofs, size, count;
00608     const size_t cert_hdr_size = sizeof *pCert - sizeof pCert->bCertificate;
00609 
00610     TRACE("%p %d %p\n", handle, index, pCert);
00611 
00612     if( !IMAGEHLP_GetCertificateOffset( handle, index, &ofs, &size ) )
00613         return FALSE;
00614 
00615     if( size < cert_hdr_size )
00616         return FALSE;
00617 
00618     offset = SetFilePointer( handle, ofs, NULL, FILE_BEGIN );
00619     if( offset == INVALID_SET_FILE_POINTER )
00620         return FALSE;
00621 
00622     r = ReadFile( handle, pCert, cert_hdr_size, &count, NULL );
00623     if( !r )
00624         return FALSE;
00625     if( count != cert_hdr_size )
00626         return FALSE;
00627 
00628     TRACE("OK\n");
00629 
00630     return TRUE;
00631 }
00632 
00633 /* Finds the section named section in the array of IMAGE_SECTION_HEADERs hdr.  If
00634  * found, returns the offset to the section.  Otherwise returns 0.  If the section
00635  * is found, optionally returns the size of the section (in size) and the base
00636  * address of the section (in base.)
00637  */
00638 static DWORD IMAGEHLP_GetSectionOffset( IMAGE_SECTION_HEADER *hdr,
00639     DWORD num_sections, LPCSTR section, PDWORD size, PDWORD base )
00640 {
00641     DWORD i, offset = 0;
00642 
00643     for( i = 0; !offset && i < num_sections; i++, hdr++ )
00644     {
00645         if( !memcmp( hdr->Name, section, strlen(section) ) )
00646         {
00647             offset = hdr->PointerToRawData;
00648             if( size )
00649                 *size = hdr->SizeOfRawData;
00650             if( base )
00651                 *base = hdr->VirtualAddress;
00652         }
00653     }
00654     return offset;
00655 }
00656 
00657 /* Calls DigestFunction e bytes at offset offset from the file mapped at map.
00658  * Returns the return value of DigestFunction, or FALSE if the data is not available.
00659  */
00660 static BOOL IMAGEHLP_ReportSectionFromOffset( DWORD offset, DWORD size,
00661     BYTE *map, DWORD fileSize, DIGEST_FUNCTION DigestFunction, DIGEST_HANDLE DigestHandle )
00662 {
00663     if( offset + size > fileSize )
00664     {
00665         SetLastError(ERROR_INVALID_PARAMETER);
00666         return FALSE;
00667     }
00668     return DigestFunction( DigestHandle, map + offset, size );
00669 }
00670 
00671 /* Finds the section named section among the IMAGE_SECTION_HEADERs in
00672  * section_headers and calls DigestFunction for this section.  Returns
00673  * the return value from DigestFunction, or FALSE if the data could not be read.
00674  */
00675 static BOOL IMAGEHLP_ReportSection( IMAGE_SECTION_HEADER *section_headers,
00676     DWORD num_sections, LPCSTR section, BYTE *map, DWORD fileSize,
00677     DIGEST_FUNCTION DigestFunction, DIGEST_HANDLE DigestHandle )
00678 {
00679     DWORD offset, size = 0;
00680 
00681     offset = IMAGEHLP_GetSectionOffset( section_headers, num_sections, section,
00682         &size, NULL );
00683     if( !offset )
00684         return FALSE;
00685     return IMAGEHLP_ReportSectionFromOffset( offset, size, map, fileSize,
00686             DigestFunction, DigestHandle );
00687 }
00688 
00689 /* Calls DigestFunction for all sections with the IMAGE_SCN_CNT_CODE flag set.
00690  * Returns the return value from * DigestFunction, or FALSE if a section could not be read.
00691  */
00692 static BOOL IMAGEHLP_ReportCodeSections( IMAGE_SECTION_HEADER *hdr, DWORD num_sections,
00693     BYTE *map, DWORD fileSize, DIGEST_FUNCTION DigestFunction, DIGEST_HANDLE DigestHandle )
00694 {
00695     DWORD i;
00696     BOOL ret = TRUE;
00697 
00698     for( i = 0; ret && i < num_sections; i++, hdr++ )
00699     {
00700         if( hdr->Characteristics & IMAGE_SCN_CNT_CODE )
00701             ret = IMAGEHLP_ReportSectionFromOffset( hdr->PointerToRawData,
00702                 hdr->SizeOfRawData, map, fileSize, DigestFunction, DigestHandle );
00703     }
00704     return ret;
00705 }
00706 
00707 /* Reports the import section from the file FileHandle.  If
00708  * CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO is set in DigestLevel, reports the entire
00709  * import section.
00710  * FIXME: if it's not set, the function currently fails.
00711  */
00712 static BOOL IMAGEHLP_ReportImportSection( IMAGE_SECTION_HEADER *hdr,
00713     DWORD num_sections, BYTE *map, DWORD fileSize, DWORD DigestLevel,
00714     DIGEST_FUNCTION DigestFunction, DIGEST_HANDLE DigestHandle )
00715 {
00716     BOOL ret = FALSE;
00717     DWORD offset, size, base;
00718 
00719     /* Get import data */
00720     offset = IMAGEHLP_GetSectionOffset( hdr, num_sections, ".idata", &size,
00721         &base );
00722     if( !offset )
00723         return FALSE;
00724 
00725     /* If CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO is set, the entire
00726      * section is reported.  Otherwise, the debug info section is
00727      * decoded and reported piecemeal.  See tests.  However, I haven't been
00728      * able to figure out how the native implementation decides which values
00729      * to report.  Either it's buggy or my understanding is flawed.
00730      */
00731     if( DigestLevel & CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO )
00732         ret = IMAGEHLP_ReportSectionFromOffset( offset, size, map, fileSize,
00733                 DigestFunction, DigestHandle );
00734     else
00735     {
00736         FIXME("not supported except for CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO\n");
00737         SetLastError(ERROR_INVALID_PARAMETER);
00738         ret = FALSE;
00739     }
00740 
00741     return ret;
00742 }
00743 
00744 /***********************************************************************
00745  *      ImageGetDigestStream (IMAGEHLP.@)
00746  *
00747  * Gets a stream of bytes from a PE file over which a hash might be computed to
00748  * verify that the image has not changed.  Useful for creating a certificate to
00749  * be added to the file with ImageAddCertificate.
00750  *
00751  * PARAMS
00752  *  FileHandle     [In] File for which to return a stream.
00753  *  DigestLevel    [In] Flags to control which portions of the file to return.
00754  *                      0 is allowed, as is any combination of:
00755  *                       CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO: reports the entire
00756  *                        import section rather than selected portions of it.
00757  *                       CERT_PE_IMAGE_DIGEST_DEBUG_INFO: reports the debug section.
00758  *                       CERT_PE_IMAGE_DIGEST_RESOURCES: reports the resources
00759                           section.
00760  *  DigestFunction [In] Callback function.
00761  *  DigestHandle   [In] Handle passed as first parameter to DigestFunction.
00762  *
00763  * RETURNS
00764  *  TRUE if successful.
00765  *  FALSE if unsuccessful.  GetLastError returns more about the error.
00766  *
00767  * NOTES
00768  *  Only supports 32-bit PE files, not tested with any other format.
00769  *  Reports data in the following order:
00770  *  1. The file headers are reported first
00771  *  2. Any code sections are reported next.
00772  *  3. The data (".data" and ".rdata") sections are reported next.
00773  *  4. The import section is reported next.
00774  *  5. If CERT_PE_IMAGE_DIGEST_DEBUG_INFO is set in DigestLevel, the debug section is
00775  *     reported next.
00776  *  6. If CERT_PE_IMAGE_DIGEST_RESOURCES is set in DigestLevel, the resources section
00777  *     is reported next.
00778  *
00779  * BUGS
00780  *  CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO must be specified, returns an error if not.
00781  */
00782 BOOL WINAPI ImageGetDigestStream(
00783   HANDLE FileHandle, DWORD DigestLevel,
00784   DIGEST_FUNCTION DigestFunction, DIGEST_HANDLE DigestHandle)
00785 {
00786     DWORD error = 0;
00787     BOOL ret = FALSE;
00788     DWORD offset, size, num_sections, fileSize;
00789     HANDLE hMap = INVALID_HANDLE_VALUE;
00790     BYTE *map = NULL;
00791     IMAGE_DOS_HEADER *dos_hdr;
00792     IMAGE_NT_HEADERS *nt_hdr;
00793     IMAGE_SECTION_HEADER *section_headers;
00794 
00795     TRACE("(%p, %d, %p, %p)\n", FileHandle, DigestLevel, DigestFunction,
00796         DigestHandle);
00797 
00798     /* Get the file size */
00799     if( !FileHandle )
00800         goto invalid_parameter;
00801     fileSize = GetFileSize( FileHandle, NULL );
00802     if(fileSize == INVALID_FILE_SIZE )
00803         goto invalid_parameter;
00804 
00805     /* map file */
00806     hMap = CreateFileMappingW( FileHandle, NULL, PAGE_READONLY, 0, 0, NULL );
00807     if( hMap == INVALID_HANDLE_VALUE )
00808         goto invalid_parameter;
00809     map = MapViewOfFile( hMap, FILE_MAP_COPY, 0, 0, 0 );
00810     if( !map )
00811         goto invalid_parameter;
00812 
00813     /* Read the file header */
00814     if( fileSize < sizeof(IMAGE_DOS_HEADER) )
00815         goto invalid_parameter;
00816     dos_hdr = (IMAGE_DOS_HEADER *)map;
00817 
00818     if( dos_hdr->e_magic != IMAGE_DOS_SIGNATURE )
00819         goto invalid_parameter;
00820     offset = dos_hdr->e_lfanew;
00821     if( !offset || offset > fileSize )
00822         goto invalid_parameter;
00823     ret = DigestFunction( DigestHandle, map, offset );
00824     if( !ret )
00825         goto end;
00826 
00827     /* Read the NT header */
00828     if( offset + sizeof(IMAGE_NT_HEADERS) > fileSize )
00829         goto invalid_parameter;
00830     nt_hdr = (IMAGE_NT_HEADERS *)(map + offset);
00831     if( nt_hdr->Signature != IMAGE_NT_SIGNATURE )
00832         goto invalid_parameter;
00833     /* It's clear why the checksum is cleared, but why only these size headers?
00834      */
00835     nt_hdr->OptionalHeader.SizeOfInitializedData = 0;
00836     nt_hdr->OptionalHeader.SizeOfImage = 0;
00837     nt_hdr->OptionalHeader.CheckSum = 0;
00838     size = sizeof(nt_hdr->Signature) + sizeof(nt_hdr->FileHeader) +
00839         nt_hdr->FileHeader.SizeOfOptionalHeader;
00840     ret = DigestFunction( DigestHandle, map + offset, size );
00841     if( !ret )
00842         goto end;
00843 
00844     /* Read the section headers */
00845     offset += size;
00846     num_sections = nt_hdr->FileHeader.NumberOfSections;
00847     size = num_sections * sizeof(IMAGE_SECTION_HEADER);
00848     if( offset + size > fileSize )
00849         goto invalid_parameter;
00850     ret = DigestFunction( DigestHandle, map + offset, size );
00851     if( !ret )
00852         goto end;
00853 
00854     section_headers = (IMAGE_SECTION_HEADER *)(map + offset);
00855     IMAGEHLP_ReportCodeSections( section_headers, num_sections,
00856         map, fileSize, DigestFunction, DigestHandle );
00857     IMAGEHLP_ReportSection( section_headers, num_sections, ".data",
00858         map, fileSize, DigestFunction, DigestHandle );
00859     IMAGEHLP_ReportSection( section_headers, num_sections, ".rdata",
00860         map, fileSize, DigestFunction, DigestHandle );
00861     IMAGEHLP_ReportImportSection( section_headers, num_sections,
00862         map, fileSize, DigestLevel, DigestFunction, DigestHandle );
00863     if( DigestLevel & CERT_PE_IMAGE_DIGEST_DEBUG_INFO )
00864         IMAGEHLP_ReportSection( section_headers, num_sections, ".debug",
00865             map, fileSize, DigestFunction, DigestHandle );
00866     if( DigestLevel & CERT_PE_IMAGE_DIGEST_RESOURCES )
00867         IMAGEHLP_ReportSection( section_headers, num_sections, ".rsrc",
00868             map, fileSize, DigestFunction, DigestHandle );
00869 
00870 end:
00871     if( map )
00872         UnmapViewOfFile( map );
00873     if( hMap != INVALID_HANDLE_VALUE )
00874         CloseHandle( hMap );
00875     if( error )
00876         SetLastError(error);
00877     return ret;
00878 
00879 invalid_parameter:
00880     error = ERROR_INVALID_PARAMETER;
00881     goto end;
00882 }
00883 
00884 /***********************************************************************
00885  *      ImageRemoveCertificate (IMAGEHLP.@)
00886  */
00887 BOOL WINAPI ImageRemoveCertificate(HANDLE FileHandle, DWORD Index)
00888 {
00889     DWORD size = 0, count = 0, sd_VirtualAddr = 0, offset = 0;
00890     DWORD data_size = 0, cert_size = 0, cert_size_padded = 0, ret = 0;
00891     LPVOID cert_data;
00892     BOOL r;
00893 
00894     TRACE("(%p, %d)\n", FileHandle, Index);
00895 
00896     r = ImageEnumerateCertificates(FileHandle, CERT_SECTION_TYPE_ANY, &count, NULL, 0);
00897 
00898     if ((!r) || (count == 0))
00899         return FALSE;
00900 
00901     if ((!IMAGEHLP_GetSecurityDirOffset(FileHandle, &sd_VirtualAddr, &size)) ||
00902         (!IMAGEHLP_GetCertificateOffset(FileHandle, Index, &offset, &cert_size)))
00903         return FALSE;
00904 
00905     /* Ignore any padding we have, too */
00906     if (cert_size % 8)
00907         cert_size_padded = cert_size + (8 - (cert_size % 8));
00908     else
00909         cert_size_padded = cert_size;
00910 
00911     data_size = size - (offset - sd_VirtualAddr) - cert_size_padded;
00912 
00913     if (data_size == 0)
00914     {
00915         ret = SetFilePointer(FileHandle, sd_VirtualAddr, NULL, FILE_BEGIN);
00916 
00917         if (ret == INVALID_SET_FILE_POINTER)
00918             return FALSE;
00919     }
00920     else
00921     {
00922         cert_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, data_size);
00923 
00924         if (!cert_data)
00925             return FALSE;
00926 
00927         ret = SetFilePointer(FileHandle, offset + cert_size_padded, NULL, FILE_BEGIN);
00928 
00929         if (ret == INVALID_SET_FILE_POINTER)
00930             goto error;
00931 
00932         /* Read any subsequent certificates */
00933         r = ReadFile(FileHandle, cert_data, data_size, &count, NULL);
00934 
00935         if ((!r) || (count != data_size))
00936             goto error;
00937 
00938         SetFilePointer(FileHandle, offset, NULL, FILE_BEGIN);
00939 
00940         /* Write them one index back */
00941         r = WriteFile(FileHandle, cert_data, data_size, &count, NULL);
00942 
00943         if ((!r) || (count != data_size))
00944             goto error;
00945 
00946         HeapFree(GetProcessHeap(), 0, cert_data);
00947     }
00948 
00949     /* If security directory is at end of file, trim the file */
00950     if (GetFileSize(FileHandle, NULL) == sd_VirtualAddr + size)
00951         SetEndOfFile(FileHandle);
00952 
00953     if (count == 1)
00954         r = IMAGEHLP_SetSecurityDirOffset(FileHandle, 0, 0);
00955     else
00956         r = IMAGEHLP_SetSecurityDirOffset(FileHandle, sd_VirtualAddr, size - cert_size_padded);
00957 
00958     if (!r)
00959         return FALSE;
00960 
00961     if (!IMAGEHLP_RecalculateChecksum(FileHandle))
00962         return FALSE;
00963 
00964     return TRUE;
00965 
00966 error:
00967     HeapFree(GetProcessHeap(), 0, cert_data);
00968     return FALSE;
00969 }

Generated on Fri May 25 2012 04:22:06 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.