Use a binary search to find entries in resource directories.

Fixed GetResDirEntryA/W prototypes.
This commit is contained in:
Alexandre Julliard 2000-10-19 20:29:53 +00:00
parent cc7abe1f06
commit 81800b1f6d
5 changed files with 226 additions and 174 deletions

View file

@ -791,10 +791,10 @@ HGLOBAL16 WINAPI InternalExtractIcon16(HINSTANCE16 hInstance,
PIMAGE_DOS_HEADER dheader; PIMAGE_DOS_HEADER dheader;
PIMAGE_NT_HEADERS pe_header; PIMAGE_NT_HEADERS pe_header;
PIMAGE_SECTION_HEADER pe_sections; PIMAGE_SECTION_HEADER pe_sections;
PIMAGE_RESOURCE_DIRECTORY rootresdir,iconresdir,icongroupresdir; const IMAGE_RESOURCE_DIRECTORY *rootresdir,*iconresdir,*icongroupresdir;
PIMAGE_RESOURCE_DATA_ENTRY idataent,igdataent; const IMAGE_RESOURCE_DATA_ENTRY *idataent,*igdataent;
int i,j; int i,j;
PIMAGE_RESOURCE_DIRECTORY_ENTRY xresent; const IMAGE_RESOURCE_DIRECTORY_ENTRY *xresent;
CURSORICONDIR **cids; CURSORICONDIR **cids;
fmapping = CreateFileMappingA(hFile,NULL,PAGE_READONLY|SEC_COMMIT,0,0,NULL); fmapping = CreateFileMappingA(hFile,NULL,PAGE_READONLY|SEC_COMMIT,0,0,NULL);
@ -836,7 +836,7 @@ HGLOBAL16 WINAPI InternalExtractIcon16(HINSTANCE16 hInstance,
goto end_4; /* failure */ goto end_4; /* failure */
} }
icongroupresdir = GetResDirEntryW(rootresdir,RT_GROUP_ICONW, (DWORD)rootresdir,FALSE); icongroupresdir = GetResDirEntryW(rootresdir,RT_GROUP_ICONW, rootresdir,FALSE);
if (!icongroupresdir) if (!icongroupresdir)
{ WARN("No Icongroupresourcedirectory!\n"); { WARN("No Icongroupresourcedirectory!\n");
@ -870,14 +870,15 @@ HGLOBAL16 WINAPI InternalExtractIcon16(HINSTANCE16 hInstance,
xresent = xresent+nIconIndex; xresent = xresent+nIconIndex;
for (i=0;i<n;i++,xresent++) for (i=0;i<n;i++,xresent++)
{ CURSORICONDIR *cid; {
PIMAGE_RESOURCE_DIRECTORY resdir; CURSORICONDIR *cid;
const IMAGE_RESOURCE_DIRECTORY *resdir;
/* go down this resource entry, name */ /* go down this resource entry, name */
resdir = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)rootresdir+(xresent->u2.s.OffsetToDirectory)); resdir = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)rootresdir+(xresent->u2.s.OffsetToDirectory));
/* default language (0) */ /* default language (0) */
resdir = GetResDirEntryW(resdir,(LPWSTR)0,(DWORD)rootresdir,TRUE); resdir = GetResDirEntryW(resdir,(LPWSTR)0,rootresdir,TRUE);
igdataent = (PIMAGE_RESOURCE_DATA_ENTRY)resdir; igdataent = (PIMAGE_RESOURCE_DATA_ENTRY)resdir;
/* lookup address in mapped image for virtual address */ /* lookup address in mapped image for virtual address */
@ -901,7 +902,7 @@ HGLOBAL16 WINAPI InternalExtractIcon16(HINSTANCE16 hInstance,
RetPtr[i] = LookupIconIdFromDirectoryEx(igdata,TRUE,GetSystemMetrics(SM_CXICON),GetSystemMetrics(SM_CYICON),0); RetPtr[i] = LookupIconIdFromDirectoryEx(igdata,TRUE,GetSystemMetrics(SM_CXICON),GetSystemMetrics(SM_CYICON),0);
} }
iconresdir=GetResDirEntryW(rootresdir,RT_ICONW,(DWORD)rootresdir,FALSE); iconresdir=GetResDirEntryW(rootresdir,RT_ICONW,rootresdir,FALSE);
if (!iconresdir) if (!iconresdir)
{ WARN("No Iconresourcedirectory!\n"); { WARN("No Iconresourcedirectory!\n");
@ -909,9 +910,10 @@ HGLOBAL16 WINAPI InternalExtractIcon16(HINSTANCE16 hInstance,
} }
for (i=0;i<n;i++) for (i=0;i<n;i++)
{ PIMAGE_RESOURCE_DIRECTORY xresdir; {
xresdir = GetResDirEntryW(iconresdir,(LPWSTR)(DWORD)RetPtr[i],(DWORD)rootresdir,FALSE); const IMAGE_RESOURCE_DIRECTORY *xresdir;
xresdir = GetResDirEntryW(xresdir,(LPWSTR)0,(DWORD)rootresdir,TRUE); xresdir = GetResDirEntryW(iconresdir,(LPWSTR)(DWORD)RetPtr[i],rootresdir,FALSE);
xresdir = GetResDirEntryW(xresdir,(LPWSTR)0,rootresdir,TRUE);
idataent = (PIMAGE_RESOURCE_DATA_ENTRY)xresdir; idataent = (PIMAGE_RESOURCE_DATA_ENTRY)xresdir;
idata = NULL; idata = NULL;

View file

@ -178,7 +178,7 @@ static BYTE * ICO_GetIconDirectory( LPBYTE peimage, LPicoICONDIR* lplpiID, ULONG
* returns * returns
* failure:0; success: icon handle or nr of icons (nIconIndex-1) * failure:0; success: icon handle or nr of icons (nIconIndex-1)
*/ */
static HRESULT WINAPI ICO_ExtractIconExW( static HRESULT ICO_ExtractIconExW(
LPCWSTR lpszExeFileName, LPCWSTR lpszExeFileName,
HICON * RetPtr, HICON * RetPtr,
INT nIconIndex, INT nIconIndex,
@ -202,18 +202,20 @@ static HRESULT WINAPI ICO_ExtractIconExW(
/* Map the file */ /* Map the file */
fmapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL ); fmapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
CloseHandle( hFile );
if (!fmapping) if (!fmapping)
{ {
WARN("CreateFileMapping error %ld\n", GetLastError() ); WARN("CreateFileMapping error %ld\n", GetLastError() );
goto end_1; return hRet;
} }
if ( !(peimage = MapViewOfFile(fmapping,FILE_MAP_READ,0,0,0))) if ( !(peimage = MapViewOfFile(fmapping,FILE_MAP_READ,0,0,0)))
{ {
WARN("MapViewOfFile error %ld\n", GetLastError() ); WARN("MapViewOfFile error %ld\n", GetLastError() );
goto end_2; CloseHandle( fmapping );
return hRet;
} }
CloseHandle( fmapping );
sig = USER32_GetResourceTable(peimage,&pData); sig = USER32_GetResourceTable(peimage,&pData);
@ -303,9 +305,9 @@ static HRESULT WINAPI ICO_ExtractIconExW(
PIMAGE_DOS_HEADER dheader; PIMAGE_DOS_HEADER dheader;
PIMAGE_NT_HEADERS pe_header; PIMAGE_NT_HEADERS pe_header;
PIMAGE_SECTION_HEADER pe_sections; PIMAGE_SECTION_HEADER pe_sections;
PIMAGE_RESOURCE_DIRECTORY rootresdir,iconresdir,icongroupresdir; const IMAGE_RESOURCE_DIRECTORY *rootresdir,*iconresdir,*icongroupresdir;
PIMAGE_RESOURCE_DATA_ENTRY idataent,igdataent; const IMAGE_RESOURCE_DATA_ENTRY *idataent,*igdataent;
PIMAGE_RESOURCE_DIRECTORY_ENTRY xresent; const IMAGE_RESOURCE_DIRECTORY_ENTRY *xresent;
int i,j; int i,j;
dheader = (PIMAGE_DOS_HEADER)peimage; dheader = (PIMAGE_DOS_HEADER)peimage;
@ -329,14 +331,14 @@ static HRESULT WINAPI ICO_ExtractIconExW(
if (!rootresdir) if (!rootresdir)
{ {
WARN("haven't found section for resource directory.\n"); WARN("haven't found section for resource directory.\n");
goto end_3; /* failure */ goto end; /* failure */
} }
/* search for the group icon directory */ /* search for the group icon directory */
if (!(icongroupresdir = GetResDirEntryW(rootresdir, RT_GROUP_ICONW, (DWORD)rootresdir, FALSE))) if (!(icongroupresdir = GetResDirEntryW(rootresdir, RT_GROUP_ICONW, rootresdir, FALSE)))
{ {
WARN("No Icongroupresourcedirectory!\n"); WARN("No Icongroupresourcedirectory!\n");
goto end_3; /* failure */ goto end; /* failure */
} }
iconDirCount = icongroupresdir->NumberOfNamedEntries + icongroupresdir->NumberOfIdEntries; iconDirCount = icongroupresdir->NumberOfNamedEntries + icongroupresdir->NumberOfIdEntries;
@ -344,7 +346,7 @@ static HRESULT WINAPI ICO_ExtractIconExW(
if( nIcons == 0 ) if( nIcons == 0 )
{ {
hRet = iconDirCount; hRet = iconDirCount;
goto end_3; /* success */ goto end; /* success */
} }
if( nIconIndex < 0 ) if( nIconIndex < 0 )
@ -367,7 +369,7 @@ static HRESULT WINAPI ICO_ExtractIconExW(
if (nIconIndex < 0) if (nIconIndex < 0)
{ {
WARN("resource id %d not found\n", iId); WARN("resource id %d not found\n", iId);
goto end_3; /* failure */ goto end; /* failure */
} }
} }
else else
@ -376,7 +378,7 @@ static HRESULT WINAPI ICO_ExtractIconExW(
if (nIconIndex >= iconDirCount) if (nIconIndex >= iconDirCount)
{ {
WARN("nIconIndex %d is larger than iconDirCount %d\n",nIconIndex,iconDirCount); WARN("nIconIndex %d is larger than iconDirCount %d\n",nIconIndex,iconDirCount);
goto end_3; /* failure */ goto end; /* failure */
} }
} }
@ -389,13 +391,13 @@ static HRESULT WINAPI ICO_ExtractIconExW(
for (i=0; i < nIcons; i++,xresent++) for (i=0; i < nIcons; i++,xresent++)
{ {
PIMAGE_RESOURCE_DIRECTORY resdir; const IMAGE_RESOURCE_DIRECTORY *resdir;
/* go down this resource entry, name */ /* go down this resource entry, name */
resdir = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)rootresdir+(xresent->u2.s.OffsetToDirectory)); resdir = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)rootresdir+(xresent->u2.s.OffsetToDirectory));
/* default language (0) */ /* default language (0) */
resdir = GetResDirEntryW(resdir,(LPWSTR)0,(DWORD)rootresdir,TRUE); resdir = GetResDirEntryW(resdir,(LPWSTR)0,rootresdir,TRUE);
igdataent = (PIMAGE_RESOURCE_DATA_ENTRY)resdir; igdataent = (PIMAGE_RESOURCE_DATA_ENTRY)resdir;
/* lookup address in mapped image for virtual address */ /* lookup address in mapped image for virtual address */
@ -413,22 +415,22 @@ static HRESULT WINAPI ICO_ExtractIconExW(
if (!igdata) if (!igdata)
{ {
WARN("no matching real address for icongroup!\n"); WARN("no matching real address for icongroup!\n");
goto end_3; /* failure */ goto end; /* failure */
} }
RetPtr[i] = (HICON)LookupIconIdFromDirectoryEx(igdata, TRUE, cxDesired, cyDesired, LR_DEFAULTCOLOR); RetPtr[i] = (HICON)LookupIconIdFromDirectoryEx(igdata, TRUE, cxDesired, cyDesired, LR_DEFAULTCOLOR);
} }
if (!(iconresdir=GetResDirEntryW(rootresdir,RT_ICONW,(DWORD)rootresdir,FALSE))) if (!(iconresdir=GetResDirEntryW(rootresdir,RT_ICONW,rootresdir,FALSE)))
{ {
WARN("No Iconresourcedirectory!\n"); WARN("No Iconresourcedirectory!\n");
goto end_3; /* failure */ goto end; /* failure */
} }
for (i=0; i<nIcons; i++) for (i=0; i<nIcons; i++)
{ {
PIMAGE_RESOURCE_DIRECTORY xresdir; const IMAGE_RESOURCE_DIRECTORY *xresdir;
xresdir = GetResDirEntryW(iconresdir,(LPWSTR)(DWORD)RetPtr[i],(DWORD)rootresdir,FALSE); xresdir = GetResDirEntryW(iconresdir,(LPWSTR)(DWORD)RetPtr[i],rootresdir,FALSE);
xresdir = GetResDirEntryW(xresdir,(LPWSTR)0,(DWORD)rootresdir,TRUE); xresdir = GetResDirEntryW(xresdir,(LPWSTR)0,rootresdir,TRUE);
idataent = (PIMAGE_RESOURCE_DATA_ENTRY)xresdir; idataent = (PIMAGE_RESOURCE_DATA_ENTRY)xresdir;
idata = NULL; idata = NULL;
@ -450,12 +452,9 @@ static HRESULT WINAPI ICO_ExtractIconExW(
RetPtr[i] = (HICON) CreateIconFromResourceEx(idata,idataent->Size,TRUE,0x00030000, cxDesired, cyDesired, LR_DEFAULTCOLOR); RetPtr[i] = (HICON) CreateIconFromResourceEx(idata,idataent->Size,TRUE,0x00030000, cxDesired, cyDesired, LR_DEFAULTCOLOR);
} }
hRet = S_OK; /* return first icon */ hRet = S_OK; /* return first icon */
goto end_3; /* sucess */
} /* if(sig == IMAGE_NT_SIGNATURE) */ } /* if(sig == IMAGE_NT_SIGNATURE) */
end_3: UnmapViewOfFile(peimage); /* success */ end: UnmapViewOfFile(peimage); /* success */
end_2: CloseHandle(fmapping);
end_1: _lclose( hFile);
return hRet; return hRet;
} }
@ -509,7 +508,7 @@ HRESULT WINAPI PrivateExtractIconsW (
HRESULT WINAPI PrivateExtractIconsA ( HRESULT WINAPI PrivateExtractIconsA (
LPCSTR lpstrFile, LPCSTR lpstrFile,
DWORD nIndex, INT nIndex,
DWORD sizeX, DWORD sizeX,
DWORD sizeY, DWORD sizeY,
HICON * phicon, HICON * phicon,
@ -520,7 +519,7 @@ HRESULT WINAPI PrivateExtractIconsA (
DWORD ret; DWORD ret;
LPWSTR lpwstrFile = HEAP_strdupAtoW(GetProcessHeap(), 0, lpstrFile); LPWSTR lpwstrFile = HEAP_strdupAtoW(GetProcessHeap(), 0, lpstrFile);
FIXME_(icon)("%s 0x%08lx 0x%08lx 0x%08lx %p 0x%08lx 0x%08x 0x%08lx stub\n", FIXME_(icon)("%s 0x%08x 0x%08lx 0x%08lx %p 0x%08lx 0x%08x 0x%08lx stub\n",
lpstrFile, nIndex, sizeX, sizeY, phicon, w, nIcons, y ); lpstrFile, nIndex, sizeX, sizeY, phicon, w, nIcons, y );
ret = PrivateExtractIconsW(lpwstrFile, nIndex, sizeX, sizeY, phicon, w, nIcons, y); ret = PrivateExtractIconsW(lpwstrFile, nIndex, sizeX, sizeY, phicon, w, nIcons, y);

View file

@ -122,9 +122,9 @@ static BOOL find_pe_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
PIMAGE_SECTION_HEADER sections; PIMAGE_SECTION_HEADER sections;
LPBYTE resSection; LPBYTE resSection;
DWORD resSectionSize; DWORD resSectionSize;
DWORD resDir; const void *resDir;
PIMAGE_RESOURCE_DIRECTORY resPtr; const IMAGE_RESOURCE_DIRECTORY *resPtr;
PIMAGE_RESOURCE_DATA_ENTRY resData; const IMAGE_RESOURCE_DATA_ENTRY *resData;
int i, nSections; int i, nSections;
@ -189,8 +189,7 @@ static BOOL find_pe_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
} }
/* Find resource */ /* Find resource */
resDir = (DWORD)resSection + resDir = resSection + (resDataDir->VirtualAddress - sections[i].VirtualAddress);
(resDataDir->VirtualAddress - sections[i].VirtualAddress);
resPtr = (PIMAGE_RESOURCE_DIRECTORY)resDir; resPtr = (PIMAGE_RESOURCE_DIRECTORY)resDir;
resPtr = GetResDirEntryA( resPtr, typeid, resDir, FALSE ); resPtr = GetResDirEntryA( resPtr, typeid, resDir, FALSE );

View file

@ -223,8 +223,10 @@ extern HRSRC PE_FindResourceW(HMODULE,LPCWSTR,LPCWSTR);
extern HRSRC PE_FindResourceExW(HMODULE,LPCWSTR,LPCWSTR,WORD); extern HRSRC PE_FindResourceExW(HMODULE,LPCWSTR,LPCWSTR,WORD);
extern DWORD PE_SizeofResource(HRSRC); extern DWORD PE_SizeofResource(HRSRC);
extern HGLOBAL PE_LoadResource(HMODULE,HRSRC); extern HGLOBAL PE_LoadResource(HMODULE,HRSRC);
extern PIMAGE_RESOURCE_DIRECTORY GetResDirEntryA(PIMAGE_RESOURCE_DIRECTORY,LPCSTR,DWORD,BOOL); extern const IMAGE_RESOURCE_DIRECTORY *GetResDirEntryA(const IMAGE_RESOURCE_DIRECTORY*,
extern PIMAGE_RESOURCE_DIRECTORY GetResDirEntryW(PIMAGE_RESOURCE_DIRECTORY,LPCWSTR,DWORD,BOOL); LPCSTR,LPCVOID,BOOL);
extern const IMAGE_RESOURCE_DIRECTORY *GetResDirEntryW(const IMAGE_RESOURCE_DIRECTORY*,
LPCWSTR,LPCVOID,BOOL);
/* loader/pe_image.c */ /* loader/pe_image.c */
extern WINE_MODREF *PE_LoadLibraryExA(LPCSTR, DWORD); extern WINE_MODREF *PE_LoadLibraryExA(LPCSTR, DWORD);

View file

@ -33,10 +33,10 @@ DEFAULT_DEBUG_CHANNEL(resource);
* *
* Get the resource directory of a PE module * Get the resource directory of a PE module
*/ */
static IMAGE_RESOURCE_DIRECTORY* get_resdir( HMODULE hmod ) static const IMAGE_RESOURCE_DIRECTORY* get_resdir( HMODULE hmod )
{ {
IMAGE_DATA_DIRECTORY *dir; const IMAGE_DATA_DIRECTORY *dir;
IMAGE_RESOURCE_DIRECTORY *ret = NULL; const IMAGE_RESOURCE_DIRECTORY *ret = NULL;
if (!hmod) hmod = GetModuleHandleA( NULL ); if (!hmod) hmod = GetModuleHandleA( NULL );
else if (!HIWORD(hmod)) else if (!HIWORD(hmod))
@ -52,69 +52,141 @@ static IMAGE_RESOURCE_DIRECTORY* get_resdir( HMODULE hmod )
} }
/**********************************************************************
* find_entry_by_name
*
* Find an entry by name in a resource directory
*/
static IMAGE_RESOURCE_DIRECTORY *find_entry_by_name( const IMAGE_RESOURCE_DIRECTORY *dir,
LPCWSTR name, const char *root )
{
const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry;
const IMAGE_RESOURCE_DIR_STRING_U *str;
int min, max, res, pos, namelen = strlenW(name);
entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
min = 0;
max = dir->NumberOfNamedEntries - 1;
while (min <= max)
{
pos = (min + max) / 2;
str = (IMAGE_RESOURCE_DIR_STRING_U *)(root + entry[pos].u1.s.NameOffset);
res = strncmpiW( name, str->NameString, str->Length );
if (!res && namelen == str->Length)
return (IMAGE_RESOURCE_DIRECTORY *)(root + entry[pos].u2.s.OffsetToDirectory);
if (res < 0) max = pos - 1;
else min = pos + 1;
}
/* now do a linear search just in case */
for (pos = 0; pos < dir->NumberOfNamedEntries; pos++)
{
str = (IMAGE_RESOURCE_DIR_STRING_U *)(root + entry[pos].u1.s.NameOffset);
if (namelen != str->Length) continue;
if (!strncmpiW( name, str->NameString, str->Length ))
{
ERR( "entry '%s' required linear search, please report\n", debugstr_w(name) );
return (IMAGE_RESOURCE_DIRECTORY *)(root + entry[pos].u2.s.OffsetToDirectory);
}
}
return NULL;
}
/**********************************************************************
* find_entry_by_id
*
* Find an entry by id in a resource directory
*/
static IMAGE_RESOURCE_DIRECTORY *find_entry_by_id( const IMAGE_RESOURCE_DIRECTORY *dir,
WORD id, const char *root )
{
const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry;
int min, max, pos;
entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
min = dir->NumberOfNamedEntries;
max = min + dir->NumberOfIdEntries - 1;
while (min <= max)
{
pos = (min + max) / 2;
if (entry[pos].u1.Id == id)
return (IMAGE_RESOURCE_DIRECTORY *)(root + entry[pos].u2.s.OffsetToDirectory);
if (entry[pos].u1.Id > id) max = pos - 1;
else min = pos + 1;
}
/* now do a linear search just in case */
min = dir->NumberOfNamedEntries;
max = min + dir->NumberOfIdEntries - 1;
for (pos = min; pos <= max; pos++)
{
if (entry[pos].u1.Id == id)
{
ERR( "entry %04x required linear search, please report\n", id );
return (IMAGE_RESOURCE_DIRECTORY *)(root + entry[pos].u2.s.OffsetToDirectory);
}
}
return NULL;
}
/**********************************************************************
* find_entry_default
*
* Find a default entry in a resource directory
*/
static IMAGE_RESOURCE_DIRECTORY *find_entry_default( const IMAGE_RESOURCE_DIRECTORY *dir,
const char *root )
{
const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry;
entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
if (dir->NumberOfNamedEntries || dir->NumberOfIdEntries)
return (IMAGE_RESOURCE_DIRECTORY *)(root + entry->u2.s.OffsetToDirectory);
return NULL;
}
/********************************************************************** /**********************************************************************
* GetResDirEntryW * GetResDirEntryW
* *
* Helper function - goes down one level of PE resource tree * Helper function - goes down one level of PE resource tree
* *
*/ */
PIMAGE_RESOURCE_DIRECTORY GetResDirEntryW(PIMAGE_RESOURCE_DIRECTORY resdirptr, const IMAGE_RESOURCE_DIRECTORY *GetResDirEntryW(const IMAGE_RESOURCE_DIRECTORY *resdirptr,
LPCWSTR name,DWORD root, LPCWSTR name, LPCVOID root,
BOOL allowdefault) BOOL allowdefault)
{ {
int entrynum; if (HIWORD(name))
PIMAGE_RESOURCE_DIRECTORY_ENTRY entryTable; {
int namelen; if (name[0]=='#')
{
if (HIWORD(name)) {
if (name[0]=='#') {
char buf[10]; char buf[10];
if (!WideCharToMultiByte( CP_ACP, 0, name+1, -1, buf, sizeof(buf), NULL, NULL )) if (!WideCharToMultiByte( CP_ACP, 0, name+1, -1, buf, sizeof(buf), NULL, NULL ))
return NULL; return NULL;
return GetResDirEntryW(resdirptr,(LPCWSTR)atoi(buf),root,allowdefault); return find_entry_by_id( resdirptr, atoi(buf), root );
} }
entryTable = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdirptr + 1); return find_entry_by_name( resdirptr, name, root );
namelen = strlenW(name); }
for (entrynum = 0; entrynum < resdirptr->NumberOfNamedEntries; entrynum++) else
{ {
PIMAGE_RESOURCE_DIR_STRING_U str = const IMAGE_RESOURCE_DIRECTORY *ret;
(PIMAGE_RESOURCE_DIR_STRING_U) (root + ret = find_entry_by_id( resdirptr, LOWORD(name), root );
entryTable[entrynum].u1.s.NameOffset); if (!ret && !name && allowdefault) ret = find_entry_default( resdirptr, root );
if(namelen != str->Length) return ret;
continue;
if(strncmpiW(name,str->NameString,str->Length)==0)
return (PIMAGE_RESOURCE_DIRECTORY) (
root +
entryTable[entrynum].u2.s.OffsetToDirectory);
}
return NULL;
} else {
entryTable = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (
(BYTE *) resdirptr +
sizeof(IMAGE_RESOURCE_DIRECTORY) +
resdirptr->NumberOfNamedEntries * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY));
for (entrynum = 0; entrynum < resdirptr->NumberOfIdEntries; entrynum++)
if ((DWORD)entryTable[entrynum].u1.Name == (DWORD)name)
return (PIMAGE_RESOURCE_DIRECTORY) (
root +
entryTable[entrynum].u2.s.OffsetToDirectory);
/* just use first entry if no default can be found */
if (allowdefault && !name && resdirptr->NumberOfIdEntries)
return (PIMAGE_RESOURCE_DIRECTORY) (
root +
entryTable[0].u2.s.OffsetToDirectory);
return NULL;
} }
} }
/********************************************************************** /**********************************************************************
* GetResDirEntryA * GetResDirEntryA
*/ */
PIMAGE_RESOURCE_DIRECTORY GetResDirEntryA( PIMAGE_RESOURCE_DIRECTORY resdirptr, const IMAGE_RESOURCE_DIRECTORY *GetResDirEntryA( const IMAGE_RESOURCE_DIRECTORY *resdirptr,
LPCSTR name, DWORD root, LPCSTR name, LPCVOID root,
BOOL allowdefault ) BOOL allowdefault )
{ {
PIMAGE_RESOURCE_DIRECTORY retv; const IMAGE_RESOURCE_DIRECTORY *retv;
LPWSTR nameW = HIWORD(name)? HEAP_strdupAtoW( GetProcessHeap(), 0, name ) LPWSTR nameW = HIWORD(name)? HEAP_strdupAtoW( GetProcessHeap(), 0, name )
: (LPWSTR)name; : (LPWSTR)name;
@ -136,42 +208,34 @@ PIMAGE_RESOURCE_DIRECTORY GetResDirEntryA( PIMAGE_RESOURCE_DIRECTORY resdirptr,
*/ */
HRSRC PE_FindResourceExW( HMODULE hmod, LPCWSTR name, LPCWSTR type, WORD lang ) HRSRC PE_FindResourceExW( HMODULE hmod, LPCWSTR name, LPCWSTR type, WORD lang )
{ {
PIMAGE_RESOURCE_DIRECTORY resdirptr = get_resdir(hmod); const IMAGE_RESOURCE_DIRECTORY *resdirptr = get_resdir(hmod);
DWORD root; const void *root;
HRSRC result; HRSRC result;
if (!resdirptr) return 0; if (!resdirptr) return 0;
root = (DWORD) resdirptr; root = resdirptr;
if ((resdirptr = GetResDirEntryW(resdirptr, type, root, FALSE)) == NULL) if ((resdirptr = GetResDirEntryW(resdirptr, type, root, FALSE)) == NULL)
return 0; return 0;
if ((resdirptr = GetResDirEntryW(resdirptr, name, root, FALSE)) == NULL) if ((resdirptr = GetResDirEntryW(resdirptr, name, root, FALSE)) == NULL)
return 0; return 0;
/* 1. Exact specified language */ /* 1. Exact specified language */
result = (HANDLE)GetResDirEntryW(resdirptr, (LPCWSTR)(UINT)lang, root, FALSE); if ((result = (HRSRC)find_entry_by_id( resdirptr, lang, root ))) goto found;
if (!result)
{
/* 2. Language with neutral sublanguage */ /* 2. Language with neutral sublanguage */
lang = MAKELANGID(PRIMARYLANGID(lang), SUBLANG_NEUTRAL); lang = MAKELANGID(PRIMARYLANGID(lang), SUBLANG_NEUTRAL);
result = (HANDLE)GetResDirEntryW(resdirptr, (LPCWSTR)(UINT)lang, root, FALSE); if ((result = (HRSRC)find_entry_by_id( resdirptr, lang, root ))) goto found;
}
if (!result)
{
/* 3. Neutral language with neutral sublanguage */ /* 3. Neutral language with neutral sublanguage */
lang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL); lang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
result = (HANDLE)GetResDirEntryW(resdirptr, (LPCWSTR)(UINT)lang, root, FALSE); if ((result = (HRSRC)find_entry_by_id( resdirptr, lang, root ))) goto found;
}
if (!result)
{
/* 4. Neutral language with default sublanguage */ /* 4. Neutral language with default sublanguage */
lang = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT); lang = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
result = (HANDLE)GetResDirEntryW(resdirptr, (LPCWSTR)(UINT)lang, root, FALSE); result = (HRSRC)find_entry_by_id( resdirptr, lang, root );
}
found:
return result; return result;
} }
@ -189,14 +253,14 @@ HRSRC PE_FindResourceExW( HMODULE hmod, LPCWSTR name, LPCWSTR type, WORD lang )
*/ */
HRSRC PE_FindResourceW( HMODULE hmod, LPCWSTR name, LPCWSTR type ) HRSRC PE_FindResourceW( HMODULE hmod, LPCWSTR name, LPCWSTR type )
{ {
PIMAGE_RESOURCE_DIRECTORY resdirptr = get_resdir(hmod); const IMAGE_RESOURCE_DIRECTORY *resdirptr = get_resdir(hmod);
DWORD root; const void *root;
HRSRC result; HRSRC result;
WORD lang; WORD lang;
if (!resdirptr) return 0; if (!resdirptr) return 0;
root = (DWORD) resdirptr; root = resdirptr;
if ((resdirptr = GetResDirEntryW(resdirptr, type, root, FALSE)) == NULL) if ((resdirptr = GetResDirEntryW(resdirptr, type, root, FALSE)) == NULL)
return 0; return 0;
if ((resdirptr = GetResDirEntryW(resdirptr, name, root, FALSE)) == NULL) if ((resdirptr = GetResDirEntryW(resdirptr, name, root, FALSE)) == NULL)
@ -204,42 +268,28 @@ HRSRC PE_FindResourceW( HMODULE hmod, LPCWSTR name, LPCWSTR type )
/* 1. Neutral language with neutral sublanguage */ /* 1. Neutral language with neutral sublanguage */
lang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL); lang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
result = (HANDLE)GetResDirEntryW(resdirptr, (LPCWSTR)(UINT)lang, root, FALSE); if ((result = (HRSRC)find_entry_by_id( resdirptr, lang, root ))) goto found;
if (!result)
{
/* 2. Neutral language with default sublanguage */ /* 2. Neutral language with default sublanguage */
lang = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT); lang = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
result = (HANDLE)GetResDirEntryW(resdirptr, (LPCWSTR)(UINT)lang, root, FALSE); if ((result = (HRSRC)find_entry_by_id( resdirptr, lang, root ))) goto found;
}
if (!result)
{
/* 3. Current locale lang id */ /* 3. Current locale lang id */
lang = LANGIDFROMLCID(GetUserDefaultLCID()); lang = LANGIDFROMLCID(GetUserDefaultLCID());
result = (HANDLE)GetResDirEntryW(resdirptr, (LPCWSTR)(UINT)lang, root, FALSE); if ((result = (HRSRC)find_entry_by_id( resdirptr, lang, root ))) goto found;
}
if (!result)
{
/* 4. Current locale lang id with neutral sublanguage */ /* 4. Current locale lang id with neutral sublanguage */
lang = MAKELANGID(PRIMARYLANGID(lang), SUBLANG_NEUTRAL); lang = MAKELANGID(PRIMARYLANGID(lang), SUBLANG_NEUTRAL);
result = (HANDLE)GetResDirEntryW(resdirptr, (LPCWSTR)(UINT)lang, root, FALSE); if ((result = (HRSRC)find_entry_by_id( resdirptr, lang, root ))) goto found;
}
if (!result)
{
/* 5. (!) LANG_ENGLISH, SUBLANG_DEFAULT */ /* 5. (!) LANG_ENGLISH, SUBLANG_DEFAULT */
lang = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT); lang = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
result = (HANDLE)GetResDirEntryW(resdirptr, (LPCWSTR)(UINT)lang, root, FALSE); if ((result = (HRSRC)find_entry_by_id( resdirptr, lang, root ))) goto found;
}
if (!result)
{
/* 6. Return first in the list */ /* 6. Return first in the list */
result = (HANDLE)GetResDirEntryW(resdirptr, (LPCWSTR)(UINT)0, root, TRUE); result = (HRSRC)find_entry_default( resdirptr, root );
}
found:
return result; return result;
} }
@ -270,8 +320,8 @@ DWORD PE_SizeofResource( HANDLE hRsrc )
BOOL WINAPI EnumResourceTypesA( HMODULE hmod, ENUMRESTYPEPROCA lpfun, LONG lparam) BOOL WINAPI EnumResourceTypesA( HMODULE hmod, ENUMRESTYPEPROCA lpfun, LONG lparam)
{ {
int i; int i;
PIMAGE_RESOURCE_DIRECTORY resdir = get_resdir(hmod); const IMAGE_RESOURCE_DIRECTORY *resdir = get_resdir(hmod);
PIMAGE_RESOURCE_DIRECTORY_ENTRY et; const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
BOOL ret; BOOL ret;
if (!resdir) return FALSE; if (!resdir) return FALSE;
@ -312,8 +362,8 @@ BOOL WINAPI EnumResourceTypesA( HMODULE hmod, ENUMRESTYPEPROCA lpfun, LONG lpara
BOOL WINAPI EnumResourceTypesW( HMODULE hmod, ENUMRESTYPEPROCW lpfun, LONG lparam) BOOL WINAPI EnumResourceTypesW( HMODULE hmod, ENUMRESTYPEPROCW lpfun, LONG lparam)
{ {
int i; int i;
PIMAGE_RESOURCE_DIRECTORY resdir = get_resdir(hmod); const IMAGE_RESOURCE_DIRECTORY *resdir = get_resdir(hmod);
PIMAGE_RESOURCE_DIRECTORY_ENTRY et; const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
BOOL ret; BOOL ret;
if (!resdir) return FALSE; if (!resdir) return FALSE;
@ -351,14 +401,14 @@ BOOL WINAPI EnumResourceTypesW( HMODULE hmod, ENUMRESTYPEPROCW lpfun, LONG lpara
BOOL WINAPI EnumResourceNamesA( HMODULE hmod, LPCSTR type, ENUMRESNAMEPROCA lpfun, LONG lparam ) BOOL WINAPI EnumResourceNamesA( HMODULE hmod, LPCSTR type, ENUMRESNAMEPROCA lpfun, LONG lparam )
{ {
int i; int i;
PIMAGE_RESOURCE_DIRECTORY basedir = get_resdir(hmod); const IMAGE_RESOURCE_DIRECTORY *basedir = get_resdir(hmod);
PIMAGE_RESOURCE_DIRECTORY resdir; const IMAGE_RESOURCE_DIRECTORY *resdir;
PIMAGE_RESOURCE_DIRECTORY_ENTRY et; const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
BOOL ret; BOOL ret;
if (!basedir) return FALSE; if (!basedir) return FALSE;
if (!(resdir = GetResDirEntryA(basedir,type,(DWORD)basedir,FALSE))) return FALSE; if (!(resdir = GetResDirEntryA(basedir,type,basedir,FALSE))) return FALSE;
et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1); et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
ret = FALSE; ret = FALSE;
@ -396,14 +446,14 @@ BOOL WINAPI EnumResourceNamesA( HMODULE hmod, LPCSTR type, ENUMRESNAMEPROCA lpfu
BOOL WINAPI EnumResourceNamesW( HMODULE hmod, LPCWSTR type, ENUMRESNAMEPROCW lpfun, LONG lparam ) BOOL WINAPI EnumResourceNamesW( HMODULE hmod, LPCWSTR type, ENUMRESNAMEPROCW lpfun, LONG lparam )
{ {
int i; int i;
PIMAGE_RESOURCE_DIRECTORY basedir = get_resdir(hmod); const IMAGE_RESOURCE_DIRECTORY *basedir = get_resdir(hmod);
PIMAGE_RESOURCE_DIRECTORY resdir; const IMAGE_RESOURCE_DIRECTORY *resdir;
PIMAGE_RESOURCE_DIRECTORY_ENTRY et; const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
BOOL ret; BOOL ret;
if (!basedir) return FALSE; if (!basedir) return FALSE;
resdir = GetResDirEntryW(basedir,type,(DWORD)basedir,FALSE); resdir = GetResDirEntryW(basedir,type,basedir,FALSE);
if (!resdir) if (!resdir)
return FALSE; return FALSE;
et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1); et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
@ -440,14 +490,14 @@ BOOL WINAPI EnumResourceLanguagesA( HMODULE hmod, LPCSTR type, LPCSTR name,
ENUMRESLANGPROCA lpfun, LONG lparam ) ENUMRESLANGPROCA lpfun, LONG lparam )
{ {
int i; int i;
PIMAGE_RESOURCE_DIRECTORY basedir = get_resdir(hmod); const IMAGE_RESOURCE_DIRECTORY *basedir = get_resdir(hmod);
PIMAGE_RESOURCE_DIRECTORY resdir; const IMAGE_RESOURCE_DIRECTORY *resdir;
PIMAGE_RESOURCE_DIRECTORY_ENTRY et; const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
BOOL ret; BOOL ret;
if (!basedir) return FALSE; if (!basedir) return FALSE;
if (!(resdir = GetResDirEntryA(basedir,type,(DWORD)basedir,FALSE))) return FALSE; if (!(resdir = GetResDirEntryA(basedir,type,basedir,FALSE))) return FALSE;
if (!(resdir = GetResDirEntryA(resdir,name,(DWORD)basedir,FALSE))) return FALSE; if (!(resdir = GetResDirEntryA(resdir,name,basedir,FALSE))) return FALSE;
et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1); et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
ret = FALSE; ret = FALSE;
@ -468,17 +518,17 @@ BOOL WINAPI EnumResourceLanguagesW( HMODULE hmod, LPCWSTR type, LPCWSTR name,
ENUMRESLANGPROCW lpfun, LONG lparam ) ENUMRESLANGPROCW lpfun, LONG lparam )
{ {
int i; int i;
PIMAGE_RESOURCE_DIRECTORY basedir = get_resdir(hmod); const IMAGE_RESOURCE_DIRECTORY *basedir = get_resdir(hmod);
PIMAGE_RESOURCE_DIRECTORY resdir; const IMAGE_RESOURCE_DIRECTORY *resdir;
PIMAGE_RESOURCE_DIRECTORY_ENTRY et; const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
BOOL ret; BOOL ret;
if (!basedir) return FALSE; if (!basedir) return FALSE;
resdir = GetResDirEntryW(basedir,type,(DWORD)basedir,FALSE); resdir = GetResDirEntryW(basedir,type,basedir,FALSE);
if (!resdir) if (!resdir)
return FALSE; return FALSE;
resdir = GetResDirEntryW(resdir,name,(DWORD)basedir,FALSE); resdir = GetResDirEntryW(resdir,name,basedir,FALSE);
if (!resdir) if (!resdir)
return FALSE; return FALSE;
et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1); et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);