サポートしない、というのが一番楽だとは思いますが…
Makefile 中のリンカオプションで以下のようになっている場所を
-subsystem:windows
-subsystem:console
それぞれ、以下のように書き換える
-subsystem:windows,5.0
-subsystem:console,5.0
- EncodePointer() は標準ライブラリのスタートアップコードで使用されている (crt0dat.c:_init_pointers()など) ので、スタートアップ実行前に呼び出し可能になっている必要がある
- 典型的な Win32 API の呼び出しは
call DWORD PTR __imp__EncodePointer@4
のように行われる。 - 本来の
__imp__EncodePointer@4
は kernel32.lib にあるが、ここではそれをオーバーライドして、xyzzyEncodePointer()が呼び出されるようにしている。
以下のコードを MASM (ml.exe) でアセンブルし、できたオブジェクトをリンク対象に入れる
; EndecodePointerOverride.asm
.model flat
EXTRN _xyzzyEncodePointer@4:PROC
EXTRN _xyzzyDecodePointer@4:PROC
EXTERNDEF __imp__EncodePointer@4:DWORD
EXTERNDEF __imp__DecodePointer@4:DWORD
.data
__imp__EncodePointer@4 dd _xyzzyEncodePointer@4
__imp__DecodePointer@4 dd _xyzzyDecodePointer@4
end
以下の C++ コードを追加する
- kernel32に
EncodePointer()
等があれば、それを使用する。 - 無ければ、与えられたポインタをそのまま返す。
// EndecodePointer.cc
#include <windows.h>
#define PROC_PTR_UNINITIALIZED ((void*)1)
static void *
getModuleProcAddress (void *procPtr, const char *szModule, const char *szProc)
{
if (PROC_PTR_UNINITIALIZED == procPtr) {
void *p = 0;
HMODULE h = GetModuleHandleA (szModule);
if (h) {
p = GetProcAddress (h, szProc);
}
procPtr = p;
}
return procPtr;
}
extern "C" void * __stdcall
xyzzyEncodePointer (void *ptr)
{
const char szModule[] = "KERNEL32";
const char szProc[] = "EncodePointer";
typedef void *(WINAPI *FUNC)(void *);
static void *procPtr = PROC_PTR_UNINITIALIZED;
procPtr = getModuleProcAddress (procPtr, szModule, szProc);
if (procPtr) {
ptr = ((FUNC)procPtr)(ptr);
}
return ptr;
}
extern "C" void * __stdcall
xyzzyDecodePointer (void *ptr)
{
const char szModule[] = "KERNEL32";
const char szProc[] = "DecodePointer";
typedef void *(WINAPI *FUNC)(void *);
static void *procPtr = PROC_PTR_UNINITIALIZED;
procPtr = getModuleProcAddress (procPtr, szModule, szProc);
if (procPtr) {
ptr = ((FUNC)procPtr)(ptr);
}
return ptr;
}
SetDllDirectory() は Windows XP SP1 以降なので、無条件で使わないようにする
// src/init.cc
static int
init_root_app (HINSTANCE hinst, int passed_cmdshow, int &ole_initialized)
{
...
- SetDllDirectory("");
+ {
+ typedef BOOL (WINAPI* SETDLLDIRECTORY)(LPCTSTR);
+ static SETDLLDIRECTORY fnSetDllDirectory = 0;
+ if(fnSetDllDirectory == 0) {
+ fnSetDllDirectory = (SETDLLDIRECTORY) GetProcAddress(GetModuleHandle("KERNEL32"), "SetDllDirectoryA");
+ }
+ if(fnSetDllDirectory) {
+ fnSetDllDirectory("");
+ }
+ }
...