#if defined(UNICODE) && defined(_M_IX86) // compile only when needed!
#include "gnul.h"
LONG GnulWinVersion;
// Checks whether the function name has small letters and ends with capital "W"
// Patches the function name if so and returns 1.
// Otherwise, it returns 0.
static __inline char IsWinW(char*p) { _asm{
// char c,sm=-1;
// for (; c=*p++;) {
// if ('a'<=c && c<='z') sm=0; // detect small letters
// if (c=='W' && *p==sm) { // detect 'W' at string end
// p[-1]='A'
// return 1;
// }
// }
// return 0;
mov ah,-1 // never detect string end
xchg esi,ecx // save ESI
l: lodsb
cmp al,1
jc e // return with carry set
cmp al,'a'
jb w
cmp al,'z'
jae w
mov ah,0 // detect string end
w: cmp al,'W'
jne l
cmp [esi],ah // string end after 'W'?
jnz l
mov byte ptr [esi-1],'A' // patch in-place to 'A' and return with carry clear
e: mov esi,ecx // restore ESI
setnc al
}}
#ifndef GNULNOFROMTO
static const char* _fastcall StrEnd(const char* p) {
return p+lstrlenA(p)+1;
}
#endif
static __inline const char* IsCandidate(char*fname, const char*fromto) {
if (IsWinW(fname)) return fname;
#ifndef GNULNOFROMTO
if (fromto) while (*fromto) {
const char*p = StrEnd(fromto);// get pointer to following ANSI name
if (!lstrcmpA(fromto,fname)) return p;
fromto=StrEnd(p); // skip ANSI name to next UNICODE name
}
#endif
return NULL;
}
#ifndef GNULNOLIST
# ifdef _DEBUG
static _declspec(naked) void* _fastcall StackAlloc(int ecx) { _asm{
pop edx // fetch return address
sub esp,ecx // make room
mov eax,esp // return pointer
jmp edx
}}
static _declspec(naked) void _fastcall StackFree(int ecx) { _asm{
pop edx
add esp,ecx
jmp edx
}}
# else
static __forceinline void* _fastcall StackAlloc(int esi) { _asm{
sub esp,esi // make room
mov eax,esp // return pointer
}}
static __forceinline _fastcall StackFree(int esi) { _asm{
add esp,esi
}}
# endif
#endif
void WINAPI GnulInit(HINSTANCE hModule, PCSTR fromto, const PCWSTR *list) {
#ifdef GNULTEST
GnulWinVersion = -1;
#else
GnulWinVersion = GetVersion();
#endif
if (GnulIsAnsi()) { // Do nothing on UNICODE-able platforms
typedef int (WINAPI*lstrlenW_t)(PCWSTR); // needed for "volatile" keyword effect
volatile lstrlenW_t saved_lstrlenW = lstrlenW;// save the lstrlenW pointer (that will later change to lstrlenA)
/* Helper macro - RVA to pointer */
# define PTR(RVA) (void*)((UINT_PTR)(hModule) + (UINT_PTR)(RVA))
PIMAGE_DOS_HEADER pDosHeader = (void*)hModule;
PIMAGE_NT_HEADERS pNTHeaders = PTR(pDosHeader->e_lfanew);
PIMAGE_DATA_DIRECTORY pDataDir = pNTHeaders->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_IMPORT;
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = PTR(pDataDir->VirtualAddress);
DWORD prot;
VirtualProtect(pImportDesc,pDataDir->Size,PAGE_READWRITE,&prot); // unlock entire .idata section
for (; pImportDesc->Characteristics; pImportDesc++) {
PIMAGE_IMPORT_BY_NAME pImportEntry, *ppImportEntry;
FARPROC* pIAT;
HMODULE hMod = 0;
ppImportEntry = PTR(pImportDesc->OriginalFirstThunk);
for (pIAT = PTR(pImportDesc->FirstThunk); *ppImportEntry; ppImportEntry++, pIAT++) {
const char *p;
pImportEntry = PTR(*ppImportEntry);
p = IsCandidate(pImportEntry->Name,fromto);
if (p) {
FARPROC pf;
if (!hMod) hMod = LoadLibraryA(PTR(pImportDesc->Name)); // delay-load DLL
pf = GetProcAddress(hMod,p);
if (pf) *pIAT = pf; // patch address
}
}
if (hMod) {FreeLibrary(hMod); hMod=0;}
}
VirtualProtect(pImportDesc,pDataDir->Size,prot,&prot);
#ifndef GNULNOLIST
if (list) {
PCWSTR s;
for (; s = *list; list++) {
int i = saved_lstrlenW(s)+1;
int j = (i*sizeof(WCHAR)+3)&~3;
// WideCharToMultiByte() does not handle overlapping strings, alloc a buffer
PSTR p = StackAlloc(j);
DWORD prot;
WideCharToMultiByte(CP_ACP,0,s,i,p,j,NULL,NULL);
VirtualProtect((void*)s,j,PAGE_READWRITE,&prot); // unlock possibly write-protected (.text) section
lstrcpyA((PSTR)s,p);
VirtualProtect((void*)s,j,prot,&prot);
StackFree(j);
}
}
#endif
}
}
#endif
Detected encoding: UTF-8 | 0
|