On 24 Dec 2001 12:33:50 -0800 Alexandre Julliard julliard@winehq.com wrote:
Instead, it finds an unimplemented procedure in Wine. So now I will
look
at LdrAccessResource (and friends) to see what's involved in
implementing
it, whatever it is.
Sounds much more problematic. LdrAccessResource itself is not too hard, but I doubt you'll get gcc to generate exactly the above code; and writing LdrAccessResource in assembly is not really an option.
Well, Shrinker is getting kind of ridiculous with its required checks for the genuine Microsoft NTDLL.DLL. Also I can't find LdrAccessResource documented anywhere. Smacks of anticompetitiveness and monopolistic intentions to me :) Is there a book on undocumented NT/2000?
I looked at the assembly of LdrAccessResource. All it is is push four args onto the stack, call an internal function, and return.
That internal function is more complicated, but it looks like it is getting a pointer to the RESOURCE entry of an image -- there are calls to RtlImageNtHeader and RtlImageDirectoryEntryToData.
So anyway, if we implemented this internal function (in C), then in theory it wouldn't be much of a big deal to code LdrAccessResource in assembly. Although it will raise a few eyebrows, we can always put in a comment similar to the one that will go in the assembler-coded EXC_CallHandler, that this code is required by Shrinker.
For those who are interested, here's the pseudo-code I've come up with for LdrAccessResource. The only missing piece is "call77F89D5F", and the exception clause -- I haven't traced those yet.
BOOL LdrAccessResource(arg1, arg2, hModule, arg4, arg5, arg6) { return _LdrAccessResource(hModule, arg4, arg5, arg6) }
BOOL _LdrAccessResource(hModule, arg2, arg3, arg4) { try { DWORD size; PIMAGE_RESOURCE_DIRECTORY *entry; PIMAGE_NT_HEADERS *ntheader; MEMORY_BASIC_INFORMATION meminfo; DWORD regionSize; void *ptr = 0; void *addr = 0;
entry = RtlImageDirectoryEntryToData( hModule, 1, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size);
if (!entry) throw STATUS_RESOURCE_DATA_NOT_FOUND;
if (arg2 < entry) hModule = LdrLoadAlternateResourceModule( hModule, 0); else { ntheader = RtlImageNtHeader(hModule&0xFFFFFFFE); if (ntheader) { if (!hModule & 0x01) regionSize = ntheader->OptionalHeader.SizeOfImage; else { ptr = ZwQueryVirtualMemory( -1, hModule&0xFFFFFFFE, 0, &meminfo, sizeof(meminfo), 0); regionSize = ptr<0 ? 0 : meminfo.RegionSize; } if (arg2 < regionSize || arg2 >= regionSize + hModule&0xFFFFFFFE) hModule = LdrLoadAlternateResourceModule( hModule, 0); } }
if (!hModule) throw STATUS_RESOURCE_DATA_NOT_FOUND;
entry = RtlImageDirectoryEntryToData( hModule, 1, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size);
if (!entry) throw STATUS_RESOURCE_DATA_NOT_FOUND;
if (hModule & 0x01) { hModule &= 0xFFFFFFFE; ntheader = RtlImageNtHeader(hModule); if (ntheader->OptionalHeader.Magic == 0x10B) addr = ntheader->OptionalHeader.DataDirectory[2].VirtualAddress; else if (ntheader->OptionalHeader.Magic == 0x20B) addr = ntheader->OptionalHeader.DataDirectory[4].VirtualAddress; else addr = 0;
if (!addr) throw STATUS_RESOURCE_DATA_NOT_FOUND;
ptr = hModule + (addr - entry);
if (!(section = RtlImageRvaToSection(ntheader, hModule, addr))) throw STATUS_RESOURCE_DATA_NOT_FOUND;
if (*arg2 > *(section+2)) { section2 = RtlImageRvaToSection(ntheader, hModule, *arg2); rtn = call77F89D5F(ntheader, hModule, *(section2+3)); ptr += *(section2+3) - *(section+3) - rtn; }
}
if (arg3) *arg3 = hModule + (*arg2 - ptr); if (arg4) *arg4 = *(arg2+1); return 0; } catch { // exception clause here } }
--Rob