@@ -1790,7 +1790,96 @@ void PEDecoder::LayoutILOnly(void *base, BOOL allowFullPE) const
1790
1790
1791
1791
#endif // #ifndef DACCESS_COMPILE
1792
1792
1793
- #ifndef FEATURE_PAL
1793
+ DWORD PEDecoder::ReadResourceDictionary (DWORD rvaOfResourceSection, DWORD rva, LPCWSTR name, BOOL *pIsDictionary) const
1794
+ {
1795
+ *pIsDictionary = FALSE ;
1796
+
1797
+ if (!CheckRva (rva, sizeof (IMAGE_RESOURCE_DIRECTORY)))
1798
+ {
1799
+ return 0 ;
1800
+ }
1801
+
1802
+ IMAGE_RESOURCE_DIRECTORY *pResourceDirectory = (IMAGE_RESOURCE_DIRECTORY *)GetRvaData (rva);
1803
+
1804
+ if (pResourceDirectory->MajorVersion != 4 )
1805
+ return 0 ;
1806
+
1807
+ if (pResourceDirectory->MinorVersion != 0 )
1808
+ return 0 ;
1809
+
1810
+ // Check to see if entire resource dictionary is accessible
1811
+ if (!CheckRva (rva + sizeof (IMAGE_RESOURCE_DIRECTORY),
1812
+ (sizeof (IMAGE_RESOURCE_DIRECTORY_ENTRY) * pResourceDirectory->NumberOfNamedEntries ) +
1813
+ (sizeof (IMAGE_RESOURCE_DIRECTORY_ENTRY) * pResourceDirectory->NumberOfIdEntries )))
1814
+ {
1815
+ return 0 ;
1816
+ }
1817
+
1818
+ IMAGE_RESOURCE_DIRECTORY_ENTRY* pDirectoryEntries = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)GetRvaData (rva + sizeof (IMAGE_RESOURCE_DIRECTORY));
1819
+
1820
+ // A fast implementation of resource lookup uses a binary search, but our needs are simple, and a linear search
1821
+ // is easier to prove correct, so do that instead.
1822
+ DWORD iEntryCount = (DWORD)pResourceDirectory->NumberOfNamedEntries + (DWORD)pResourceDirectory->NumberOfIdEntries ;
1823
+
1824
+ for (DWORD iEntry = 0 ; iEntry < iEntryCount; iEntry++)
1825
+ {
1826
+ BOOL foundEntry = FALSE ;
1827
+
1828
+ if (((UINT_PTR)name) <= 0xFFFF )
1829
+ {
1830
+ // name is id
1831
+ if (pDirectoryEntries[iEntry].Name == (DWORD)name)
1832
+ foundEntry = TRUE ;
1833
+ }
1834
+ else
1835
+ {
1836
+ // name is string
1837
+ DWORD entryName = pDirectoryEntries[iEntry].Name ;
1838
+ if (!(entryName & IMAGE_RESOURCE_NAME_IS_STRING))
1839
+ continue ;
1840
+
1841
+ DWORD entryNameRva = (entryName & ~IMAGE_RESOURCE_NAME_IS_STRING) + rvaOfResourceSection;
1842
+
1843
+ if (!CheckRva (entryNameRva, sizeof (WORD)))
1844
+ return 0 ;
1845
+
1846
+ size_t entryNameLen = *(WORD*)GetRvaData (entryNameRva);
1847
+ if (wcslen (name) != entryNameLen)
1848
+ continue ;
1849
+
1850
+ if (!CheckRva (entryNameRva, (COUNT_T)(sizeof (WORD) * (1 + entryNameLen))))
1851
+ return 0 ;
1852
+
1853
+ if (memcmp ((WCHAR*)GetRvaData (entryNameRva + sizeof (WORD)), name, entryNameLen * sizeof (WCHAR)) == 0 )
1854
+ foundEntry = TRUE ;
1855
+ }
1856
+
1857
+ if (!foundEntry)
1858
+ continue ;
1859
+
1860
+ *pIsDictionary = !!(pDirectoryEntries[iEntry].OffsetToData & IMAGE_RESOURCE_DATA_IS_DIRECTORY);
1861
+ DWORD offsetToData = pDirectoryEntries[iEntry].OffsetToData & ~IMAGE_RESOURCE_DATA_IS_DIRECTORY;
1862
+ DWORD dataRva = rvaOfResourceSection + offsetToData;
1863
+ return dataRva;
1864
+ }
1865
+
1866
+ return 0 ;
1867
+ }
1868
+
1869
+ DWORD PEDecoder::ReadResourceDataEntry (DWORD rva, COUNT_T *pSize) const
1870
+ {
1871
+ *pSize = 0 ;
1872
+
1873
+ if (!CheckRva (rva, sizeof (IMAGE_RESOURCE_DATA_ENTRY)))
1874
+ {
1875
+ return 0 ;
1876
+ }
1877
+
1878
+ IMAGE_RESOURCE_DATA_ENTRY *pDataEntry = (IMAGE_RESOURCE_DATA_ENTRY *)GetRvaData (rva);
1879
+ *pSize = pDataEntry->Size ;
1880
+ return pDataEntry->OffsetToData ;
1881
+ }
1882
+
1794
1883
void * PEDecoder::GetWin32Resource (LPCWSTR lpName, LPCWSTR lpType, COUNT_T *pSize /* =NULL*/ ) const
1795
1884
{
1796
1885
CONTRACTL {
@@ -1800,31 +1889,57 @@ void * PEDecoder::GetWin32Resource(LPCWSTR lpName, LPCWSTR lpType, COUNT_T *pSiz
1800
1889
GC_NOTRIGGER;
1801
1890
} CONTRACTL_END;
1802
1891
1803
- if (pSize != NULL )
1804
- *pSize = 0 ;
1892
+ COUNT_T sizeUnused = 0 ; // Use this variable if pSize is null
1893
+ if (pSize == NULL )
1894
+ pSize = &sizeUnused;
1895
+
1896
+ *pSize = 0 ;
1897
+
1898
+ if (!HasDirectoryEntry (IMAGE_DIRECTORY_ENTRY_RESOURCE))
1899
+ return NULL ;
1900
+
1901
+ COUNT_T resourceDataSize = 0 ;
1902
+ IMAGE_DATA_DIRECTORY *pDir = GetDirectoryEntry (IMAGE_DIRECTORY_ENTRY_RESOURCE);
1805
1903
1806
- HMODULE hModule = (HMODULE) dac_cast<TADDR>(GetBase ());
1904
+ if (pDir->VirtualAddress == 0 )
1905
+ return NULL ;
1807
1906
1808
- // Use the Win32 functions to decode the resources
1907
+ BOOL isDictionary = FALSE ;
1908
+ DWORD nameTableRva = ReadResourceDictionary (pDir->VirtualAddress , pDir->VirtualAddress , lpType, &isDictionary);
1809
1909
1810
- HRSRC hResource = WszFindResourceEx (hModule, lpType, lpName, MAKELANGID (LANG_NEUTRAL, SUBLANG_NEUTRAL));
1811
- if (!hResource)
1910
+ if (!isDictionary)
1911
+ return NULL ;
1912
+
1913
+ if (nameTableRva == 0 )
1812
1914
return NULL ;
1813
1915
1814
- HGLOBAL hLoadedResource = :: LoadResource (hModule, hResource );
1815
- if (!hLoadedResource )
1916
+ DWORD languageTableRva = ReadResourceDictionary (pDir-> VirtualAddress , nameTableRva, lpName, &isDictionary );
1917
+ if (!isDictionary )
1816
1918
return NULL ;
1817
1919
1818
- PVOID pResource = ::LockResource (hLoadedResource);
1819
- if (!pResource)
1920
+ if (languageTableRva == 0 )
1820
1921
return NULL ;
1821
1922
1822
- if (pSize != NULL )
1823
- *pSize = ::SizeofResource (hModule, hResource);
1923
+ // This api is designed to find resources with LANGID = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)
1924
+ // This translates to LANGID 0 as the initial lookup point, which is sufficient for the needs of this api at this time
1925
+ // (FindResource in the Windows api implements a large number of fallback paths which this api does not implement)
1926
+
1927
+ DWORD resourceDataEntryRva = ReadResourceDictionary (pDir->VirtualAddress , languageTableRva, 0 , &isDictionary);
1928
+ if (isDictionary) // This must not be a resource dictionary itself
1929
+ return NULL ;
1930
+
1931
+ if (resourceDataEntryRva == 0 )
1932
+ return NULL ;
1933
+
1934
+ DWORD resourceDataRva = ReadResourceDataEntry (resourceDataEntryRva, pSize);
1935
+ if (!CheckRva (resourceDataRva, *pSize))
1936
+ {
1937
+ *pSize = 0 ;
1938
+ return NULL ;
1939
+ }
1824
1940
1825
- return pResource ;
1941
+ return ( void *) GetRvaData (resourceDataRva) ;
1826
1942
}
1827
- #endif // FEATURE_PAL
1828
1943
1829
1944
BOOL PEDecoder::HasNativeHeader () const
1830
1945
{
0 commit comments