Skip to content

Instantly share code, notes, and snippets.

@xyzzy-17-638
Created April 10, 2012 20:55
Show Gist options
  • Save xyzzy-17-638/2354412 to your computer and use it in GitHub Desktop.
Save xyzzy-17-638/2354412 to your computer and use it in GitHub Desktop.
Windows2000 で xyzzyのマルチフレーム版を動かすための修正案

Windows2000 で xyzzyのマルチフレーム版を動かすための修正案

サポートしない、というのが一番楽だとは思いますが…

OS の環境を Windows 2000 SP4 update Rollup 1 にする

/subsystem のバージョンを 5.0 にする

Makefile 中のリンカオプションで以下のようになっている場所を

-subsystem:windows
-subsystem:console

それぞれ、以下のように書き換える

-subsystem:windows,5.0
-subsystem:console,5.0

EncodePointer(), DecodePointer() を置き換え

  • 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;
}

SetDllDirectoryA() を GetProcAddress() して使うようにする

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("");
+	    }
+	  }
	...

コピペ元

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment