Changeset 25331 in vbox for trunk/src/VBox/HostDrivers/Support/win
- Timestamp:
- Dec 11, 2009 2:17:04 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 55914
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp
r25308 r25331 35 35 #include "../SUPDrvInternal.h" 36 36 #include <excpt.h> 37 #include <ntimage.h> 38 37 39 #include <iprt/assert.h> 38 40 #include <iprt/initterm.h> … … 732 734 733 735 734 int VBOXCALL supdrvOSLdrLoad(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const uint8_t *pbImageBits) 735 { 736 NOREF(pDevExt); NOREF(pImage); NOREF(pbImageBits); 737 if (pImage->pvNtSectionObj) 738 { 739 if (!memcmp(pImage->pvImage, pbImageBits, pImage->cbImageBits)) 740 return VINF_SUCCESS; 741 742 /* trac down the difference and log it. */ 743 uint32_t cbLeft = pImage->cbImageBits; 736 /** 737 * memcmp + log. 738 * 739 * @returns Same as memcmp. 740 * @param pImage The image. 741 * @param pbImageBits The image bits ring-3 uploads. 742 * @param uRva The RVA to start comparing at. 743 * @param cb The number of bytes to compare. 744 */ 745 static int supdrvNtCompare(PSUPDRVLDRIMAGE pImage, const uint8_t *pbImageBits, uint32_t uRva, uint32_t cb) 746 { 747 int iDiff = memcmp((uint8_t const *)pImage->pvImage + uRva, pbImageBits + uRva, cb); 748 if (iDiff) 749 { 750 uint32_t cbLeft = cb; 744 751 const uint8_t *pbNativeBits = (const uint8_t *)pImage->pvImage; 745 for (size_t off = 0; cbLeft > 0; off++, cbLeft--)752 for (size_t off = uRva; cbLeft > 0; off++, cbLeft--) 746 753 if (pbNativeBits[off] != pbImageBits[off]) 747 754 { … … 751 758 RT_MIN(12, cbLeft), &pbImageBits[off]); 752 759 SUPR0Printf("VBoxDrv: Mismatch at %#x of %s: %s\n", off, pImage->szName, szBytes); 753 return VERR_LDR_MISMATCH_NATIVE; 754 } 760 break; 761 } 762 } 763 return iDiff; 764 } 765 766 int VBOXCALL supdrvOSLdrLoad(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const uint8_t *pbImageBits) 767 { 768 NOREF(pDevExt); NOREF(pImage); NOREF(pbImageBits); 769 if (pImage->pvNtSectionObj) 770 { 771 /* 772 * Usually, the entire image matches exactly. 773 */ 774 if (!memcmp(pImage->pvImage, pbImageBits, pImage->cbImageBits)) 775 return VINF_SUCCESS; 776 777 /* 778 * However, on Windows Server 2003 (sp2 x86) both import thunk tables 779 * are fixed up and we typically get a mismatch in the INIT section. 780 * 781 * So, lets see if everything matches when excluding the 782 * OriginalFirstThunk tables. To make life simpler, set the max number 783 * of imports to 16 and just record and sort the locations that needs 784 * to be excluded from the comparison. 785 */ 786 IMAGE_NT_HEADERS const *pNtHdrs; 787 pNtHdrs = (IMAGE_NT_HEADERS const *)(pbImageBits 788 + ( *(uint16_t *)pbImageBits == IMAGE_DOS_SIGNATURE 789 ? ((IMAGE_DOS_HEADER const *)pbImageBits)->e_lfanew 790 : 0)); 791 if ( pNtHdrs->Signature == IMAGE_NT_SIGNATURE 792 && pNtHdrs->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR_MAGIC 793 && pNtHdrs->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_IMPORT 794 && pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size >= sizeof(IMAGE_IMPORT_DESCRIPTOR) 795 && pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress > sizeof(IMAGE_NT_HEADERS) 796 && pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress < pImage->cbImageBits 797 ) 798 { 799 struct MyRegion 800 { 801 uint32_t uRva; 802 uint32_t cb; 803 } aExcludeRgns[16]; 804 unsigned cExcludeRgns = 0; 805 uint32_t cImpsLeft = pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size 806 / sizeof(IMAGE_IMPORT_DESCRIPTOR); 807 IMAGE_IMPORT_DESCRIPTOR const *pImp; 808 pImp = (IMAGE_IMPORT_DESCRIPTOR const *)(pbImageBits 809 + pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); 810 while ( cImpsLeft-- > 0 811 && cExcludeRgns < RT_ELEMENTS(aExcludeRgns)) 812 { 813 uint32_t uRvaThunk = pImp->OriginalFirstThunk; 814 if ( uRvaThunk > sizeof(IMAGE_NT_HEADERS) 815 && uRvaThunk <= pImage->cbImageBits - sizeof(IMAGE_THUNK_DATA) 816 && uRvaThunk != pImp->FirstThunk) 817 { 818 /* Find the size of the thunk table. */ 819 IMAGE_THUNK_DATA const *paThunk = (IMAGE_THUNK_DATA const *)(pbImageBits + uRvaThunk); 820 uint32_t cMaxThunks = (pImage->cbImageBits - uRvaThunk) / sizeof(IMAGE_THUNK_DATA); 821 uint32_t cThunks = 0; 822 while (cThunks < cMaxThunks && paThunk[cThunks].u1.Function != 0) 823 cThunks++; 824 825 /* Ordered table insert. */ 826 unsigned i = 0; 827 for (; i < cExcludeRgns; i++) 828 if (uRvaThunk < aExcludeRgns[i].uRva) 829 break; 830 if (i != cExcludeRgns) 831 memmove(&aExcludeRgns[i + 1], &aExcludeRgns[i], (cExcludeRgns - i) * sizeof(aExcludeRgns[0])); 832 aExcludeRgns[i].uRva = uRvaThunk; 833 aExcludeRgns[i].cb = cThunks * sizeof(IMAGE_THUNK_DATA); 834 cExcludeRgns++; 835 } 836 837 /* advance */ 838 pImp++; 839 } 840 841 /* 842 * Ok, do the comparison. 843 */ 844 int iDiff = 0; 845 uint32_t uRvaNext = 0; 846 for (unsigned i = 0; !iDiff && i < cExcludeRgns; i++) 847 { 848 if (uRvaNext < aExcludeRgns[i].uRva) 849 iDiff = supdrvNtCompare(pImage, pbImageBits, uRvaNext, aExcludeRgns[i].uRva - uRvaNext); 850 uRvaNext = aExcludeRgns[i].uRva + aExcludeRgns[i].cb; 851 } 852 if (!iDiff && uRvaNext < pImage->cbImageBits) 853 iDiff = supdrvNtCompare(pImage, pbImageBits, uRvaNext, pImage->cbImageBits - uRvaNext); 854 if (!iDiff) 855 return VINF_SUCCESS; 856 } 857 else 858 supdrvNtCompare(pImage, pbImageBits, 0, pImage->cbImageBits); 859 return VERR_LDR_MISMATCH_NATIVE; 755 860 } 756 861 return VERR_INTERNAL_ERROR_4; … … 768 873 } 769 874 770 NTSTATUS rc = ZwSetSystemInformation(MY_SystemUnloadGdiDriverInformation, 771 &pImage->pvNtSectionObj, sizeof(pImage->pvNtSectionObj)); 875 NTSTATUS rcNt = ZwSetSystemInformation(MY_SystemUnloadGdiDriverInformation, 876 &pImage->pvNtSectionObj, sizeof(pImage->pvNtSectionObj)); 877 if (rcNt != STATUS_SUCCESS) 878 SUPR0Printf("VBoxDrv: failed to unload '%s', rcNt=%#x\n", pImage->szName, rcNt); 772 879 pImage->pvNtSectionObj = NULL; 773 880 }
Note:
See TracChangeset
for help on using the changeset viewer.