Source file: /~heha/hs/UNI-T/he2325u.zip/src/gnul.c

#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-80