UWSCでDLLを扱う

ハフマン符号に手を出そうかと思ったし、実証コードも書いてみたけど、、、オレオレ圧縮はやめよう、そう思った。
なので、ZIPに手を出すことにした。
ZIPと言えば、zlib http://zlib.net/ だよね、ということで、これをAsmモジュール用に改造を考えたけど、、、面倒。


あれさ、Asmモジュールって制約が厳しいの。
もうだったらいっそのこと、DLLをロードしてしまえ、と思ったけど、DLLとスクリプトに分かれるのが、微妙に嫌。
じゃあ、ついにメモリーからDLLのロードに手を出すか、と思った次第。



スクリプト

http://www.codeproject.com/Tips/430684/Loading-Win32-64-DLLs-manually-without-LoadLibrary
を参考にして、前書いたGetLastError取得モジュールにAsmモジュールとあわせてマージ。

追記
Allocを2kを境に、VirtualAllocかHeapAllocかで呼び分けるように修正。
第二引数にポインターを指定した場合、第二引数のポインターは解放するよう修正(ReAllocイメージ)

Dll.uws

OPTION EXPLICIT

IFB GET_UWSC_NAME = "Dll.uws" THEN

	TEXTBLOCK _mini_dll
		TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
		AAAAAAAAyAAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4g
		RE9TIG1vZGUuDQ0KJAAAAAAAAABzqEzMN8kinzfJIp83ySKfEA9ZnzLJIp83ySOfPckinz6x
		q582ySKfPrGwnzbJIp8+sbOfNskin1JpY2g3ySKfAAAAAAAAAABQRQAATAEEADp+V1IAAAAA
		AAAAAOAAAiELAQkAAAIAAAAGAAAAAAAAWBEAAAAQAAAAIAAAAAAAEAAQAAAAAgAABQAAAAAA
		AAAFAAAAAAAAAABQAAAABAAAAAAAAAIAQAUAABAAABAAAAAAEAAAEAAAAAAAABAAAABwIQAA
		fwAAAFggAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAFAAAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAMAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAC50ZXh0AAAAqAEAAAAQAAAAAgAAAAQAAAAAAAAAAAAAAAAAACAA
		AGAucmRhdGEAAO8BAAAAIAAAAAIAAAAGAAAAAAAAAAAAAAAAAABAAABALmRhdGEAAAAIAAAA
		ADAAAAACAAAACAAAAAAAAAAAAAAAAAAAQAAAwC5yZWxvYwAAZgAAAABAAAAAAgAAAAoAAAAA
		AAAAAAAAAAAAAEAAAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKEA
		MAAQg/j/dAdQ/xUgIAAQgw0AMAAQ/zPAw1bo3/////8VFCAAEGoAaIAAAABqBGoAagFoAAAA
		QP90JCCjBDAAEP8VACAAEDPJg/j/D5XBowAwABCL8YX2dA1qAmoAagBQ/xUEIAAQi8Zew1WL
		7IPsFIM9ADAAEP8PhIYAAABWV41F7FD/FRwgABD/dQj/FQggABCL8IPGGVZqAP81BDAAEP8V
		DCAAEP91CIv4D7dF+lAPt0X4UA+3RfZQD7dF9FAPt0XyUA+3Re5QD7dF7FBoMCAAEFf/FSgg
		ABCDxChqAI1F/FBOVlf/NQAwABD/FRggABBXagD/NQQwABD/FRAgABBfXsnDgz0AMAAQ/3RH
		Vv90JAj/FQggABCDwGRQagD/NQQwABD/FQwgABD/dCQMi/D/dCQMVv8VKCAAEFboKP///4PE
		EFZqAP81BDAAEP8VECAAEF7Di0QkCIPoAHUF6Jr+//8zwEDCDAD/JQAgABD/JQQgABD/JQgg
		ABD/JQwgABD/JRAgABD/JRQgABD/JRggABD/JRwgABD/JSAgABD/JSggABAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxCAAANIgAADkIAAA8CAAAPwgAAAIIQAAGiEAACYh
		AAA2IQAAAAAAAFIhAAAAAAAAJTA0ZC8lMDJkLyUwMmQgJTAyZDolMDJkOiUwMmQuJTAzZCAl
		cwAAAJQgAAAAAAAAAAAAAEQhAAAAIAAAvCAAAAAAAAAAAAAAXiEAACggAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAMQgAADSIAAA5CAAAPAgAAD8IAAACCEAABohAAAmIQAANiEAAAAAAABSIQAA
		AAAAAHgAQ3JlYXRlRmlsZUEA3wNTZXRGaWxlUG9pbnRlcgAAtQRsc3RybGVuQQAAnQJIZWFw
		QWxsb2MAoQJIZWFwRnJlZQAAIwJHZXRQcm9jZXNzSGVhcAAAjQRXcml0ZUZpbGUA5wFHZXRM
		b2NhbFRpbWUAAEMAQ2xvc2VIYW5kbGUAS0VSTkVMMzIuZGxsAAAHA3dzcHJpbnRmQQBVU0VS
		MzIuZGxsAAAAAAAAAAAAAAAAOn5XUgAAAADAIQAAAQAAAAQAAAAEAAAAmCEAAKghAAC4IQAA
		ABAAAGwQAAAHEQAAGxAAANMhAADcIQAA4CEAAOchAAAAAAEAAgADAFdpbjMyRGxsVkMyMDA4
		LmRsbABDbG9zZUxvZwBMb2cATG9nUHV0AE9wZW5Mb2cAAAAAAAAAAAAAAAAAAAAAAAD/////
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAABQAAAAATANMBMwIzA+MEQwUTBkMHQwhzCQMJ4w
		pDDRMNgw6jDwMPkw/zAJMRcxIzEpMToxTDFSMW4xdDF6MYAxhjGMMZIxmDGeMaQxAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
		AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
	ENDTEXTBLOCK

	//Dll.Debug = 2
	DIM hDll = Dll.Import(_mini_dll), e

	DIM res = Dll.Call(hDll, e, "OpenLog", "Dll.uws.test.log")
	IF !res THEN MSGBOX("OpenLog失敗")

	Dll.Call(hDll, e, "Log", "Dll.uws ログ出力テスト<#CR>")
	Dll.Call(hDll, e, "Log", "メモリー上を呼んでます<#CR>")

	Dll.CallEx(hDll, e, "LogPut", EMPTY, 2, "uwscからメモリー上のDLLを呼ぶ(%d)<#CR>", 14)

	Dll.Unload(hDll)


	DIM name = "SetLastError", ret = 0
	MSGBOX(name + "試験")
	// DWORD値を渡す場合、第五引数は0(省略値)
	Dll.Call(ret, e, Dll.GetProcAddress(Dll.hK32, name), 12345)
	IF ret THEN
		MSGBOX(name + "(12345)の結果: " + e)
		ret = 0
	ELSE
		MSGBOX(name + " Dll.Call失敗 " + e)
	ENDIF
	Dll.Call(ret, e, name, 1234, 0, "kernel32")
	IF ret THEN
		MSGBOX(name + "(1234)の結果: " + e)
	ELSE
		MSGBOX(name + " Dll.Call失敗 " + e)
	ENDIF

	Dll.Dispose()
ENDIF


MODULE Dll
	PUBLIC hK32 = NULL
	PUBLIC Debug = 0

	DEF_DLL CreateThread(DWORD, DWORD, DWORD, DWORD, DWORD, DWORD): DWORD: kernel32
	DEF_DLL WaitForSingleObject(DWORD, DWORD): DWORD: kernel32
	DEF_DLL CloseHandle(DWORD): bool: kernel32
	DEF_DLL GetExitCodeThread(DWORD, var DWORD): bool: kernel32
	DEF_DLL VirtualAlloc(DWORD, DWORD, DWORD, DWORD): DWORD: kernel32
	DEF_DLL VirtualFree(DWORD, DWORD, DWORD): bool: kernel32
	DEF_DLL GetProcAddress(DWORD, string): DWORD: kernel32
	DEF_DLL CryptStringToBinaryW(wstring,dword,dword,dword,var dword,var dword,var dword): BOOL: crypt32
	DEF_DLL LoadLibraryW(wstring): DWORD: kernel32
	DEF_DLL FreeLibrary(DWORD): BOOL: kernel32
	DEF_DLL CryptBinaryToStringW(DWORD,DWORD,DWORD,var wstring,var DWORD): BOOL: crypt32
	DEF_DLL GetProcessHeap(): DWORD: kernel32
	DEF_DLL HeapAlloc(DWORD,DWORD,DWORD): DWORD: kernel32
	DEF_DLL HeapFree(DWORD,DWORD,DWORD): BOOL: kernel32
	DEF_DLL HeapReAlloc(DWORD,DWORD,DWORD,DWORD): DWORD: kernel32

	CONST WAIT_TIMEOUT = 258

	CONST CRYPT_STRING_BASE64HEADER        = $00000000
	CONST CRYPT_STRING_BASE64              = $00000001
	CONST CRYPT_STRING_BINARY              = $00000002
	CONST CRYPT_STRING_BASE64REQUESTHEADER = $00000003
	CONST CRYPT_STRING_HEX                 = $00000004
	CONST CRYPT_STRING_HEXASCII            = $00000005
	CONST CRYPT_STRING_BASE64_ANY          = $00000006
	CONST CRYPT_STRING_ANY                 = $00000007
	CONST CRYPT_STRING_HEX_ANY             = $00000008
	CONST CRYPT_STRING_BASE64X509CRLHEADER = $00000009
	CONST CRYPT_STRING_HEXADDR             = $0000000a
	CONST CRYPT_STRING_HEXASCIIADDR        = $0000000b
	CONST CRYPT_STRING_HEXRAW              = $0000000c
	CONST CRYPT_STRING_ASCII               = $00000010	// 勝手定義
	CONST CRYPT_STRING_HASHDATA            = $10000000
	CONST CRYPT_STRING_STRICT              = $20000000
	CONST CRYPT_STRING_NOCRLF              = $40000000
	CONST CRYPT_STRING_NOCR                = $80000000

	CONST HEAP_ALLOC_SIZE = 2048

	// Success
	CONST ELoadDLLResult_OK = 0
	// The read procedure we provided returned FALSE for a read request.
	CONST ELoadDLLResult_ReadProcError = 1
	// Bad DLL file. Wrong header or a similar error.
	CONST ELoadDLLResult_InvalidImage = 2
	// Memory allocation error.
	CONST ELoadDLLResult_MemoryAllocationError = 3
	// The DLL could not be loaded to the preferred imagebase and there is no base relocation info in the module.
	CONST ELoadDLLResult_RelocationError = 4
	// The DLL relocation data seems to be bad.
	CONST ELoadDLLResult_BadRelocationTable = 5
	// An imported DLL could not be loaded.
	CONST ELoadDLLResult_ImportModuleError = 6
	// A function was not found in an imported DLL.
	CONST ELoadDLLResult_ImportFunctionError = 6
	// Bad import table contents.
	CONST ELoadDLLResult_ImportTableError = 7
	// We do not support import directories that contain only bound import info.
	CONST ELoadDLLResult_BoundImportDirectoriesNotSupported = 8
	// Error setting the memory page protection of loaded and relocated sections.
	CONST ELoadDLLResult_ErrorSettingMemoryProtection = 9
	// The DllMain() returned FALSE or caused an exception.
	CONST ELoadDLLResult_DllMainCallError = 10
	CONST ELoadDLLResult_DLLFileNotFound = 11
	// LoadDLL() was called with wrong parameters
	CONST ELoadDLLResult_WrongFunctionParameters = -2
	CONST ELoadDLLResult_UnknownError = -1

	// Don't call the DllMain() of the loaded DLL.
	CONST ELoadDLLFlag_NoEntryCall = 1
	// Don't load the DOS/PE headers, only the data/code sections. This is useful only with LoadDLL().
	CONST ELoadDLLFlag_NoHeaders   = 2

	CONST PARA_BASE_SIZE = 84
	CONST PARA_FUNC_OFFSET = 80
	CONST PARA_LASTERR_OFFSET = 76


	DIM _proc = NULL, _data = NULL
	DIM _heap = NULL
	HASHTBL _allocs

	PROCEDURE Dll
		hK32 = LoadLibraryW("kernel32")
		IF _proc <> NULL THEN Free(_proc)
		_proc = Set(_dll_imp_code)
		_heap = GetProcessHeap()
	FEND

	PROCEDURE Dispose()
		IF _data <> NULL THEN Free(_data)
		_data = NULL
		IF _proc <> NULL THEN Free(_proc)
		_proc = NULL
		WHILE LENGTH(_allocs)
			DebugLog("Dispose() Free " + _allocs[0, HASH_KEY])
			Free(_allocs[0, HASH_KEY])
		WEND
	FEND


	FUNCTION Set(code)
		RESULT = SetString(0, code, CRYPT_STRING_ANY, $40)
	FEND

	// 戻りはtypeによって異なる
	//  type=0   : スレッド終了コード
	//  type=1   : スレッド終了コード取得失敗
	//  type=258 : スレッドハンドル
	//  type=他  : その他エラーコード(WaitForSingleObject)
	FUNCTION Run(addr, para, var type, timeout=$7FFFFFFF, unit=100)
		DIM hThread = CreateThread(0, 0, addr, para, 0, 0)
		RESULT = hThread
		type = WAIT_TIMEOUT
		WHILE timeout >= 0 AND type = WAIT_TIMEOUT
			type = WaitForSingleObject(hThread, unit)
			timeout = timeout - unit
		WEND
		IFB type = 0 THEN
			IF !GetExitCodeThread(hThread, RESULT) THEN type = 1
			CloseHandle(hThread)
		ENDIF
	FEND

	FUNCTION Alloc(size, ptr=NULL, pro=4, hf=8)	// 4:PAGE_READWRITE 8:HEAP_ZERO_MEMORY
		DIM sz = HEAP_ALLOC_SIZE
		RESULT = NULL
		IFB ptr <> NULL THEN
			IF _allocs[ptr, HASH_EXISTS] THEN sz = _allocs[ptr]
			IFB size < HEAP_ALLOC_SIZE AND sz < HEAP_ALLOC_SIZE THEN
				RESULT = _allocs[ptr, HASH_REMOVE]
				RESULT = HeapReAlloc(_heap, hf, ptr, size)
				ptr = NULL
			ENDIF
		ENDIF
		IFB RESULT = NULL THEN
			IFB size < HEAP_ALLOC_SIZE THEN
				RESULT = HeapAlloc(_heap, hf, size)
			ELSE
				RESULT = VirtualAlloc(0, size, $1000, pro)	// $1000:MEM_COMMIT
			ENDIF
		ENDIF
		IF RESULT THEN _allocs[RESULT] = size
		IFB ptr <> NULL THEN
			DIM res = _allocs[ptr, HASH_REMOVE]
			IF size < sz THEN sz = size
			DEF_DLL RtlMoveMemory(DWORD, DWORD, DWORD): kernel32
			RtlMoveMemory(RESULT, ptr, sz)
			Free(ptr)
		ENDIF
		DebugLog("Alloc(" + size + ") " + RESULT)
	FEND
	FUNCTION Free(ptr)
		DIM sz = HEAP_ALLOC_SIZE
		IFB _allocs[ptr, HASH_EXISTS] THEN
			sz = _allocs[ptr]
			RESULT = _allocs[ptr, HASH_REMOVE]
		ENDIF
		IFB sz < HEAP_ALLOC_SIZE THEN
			RESULT = HeapFree(_heap, 0, ptr)
		ELSE
			RESULT = VirtualFree(ptr, 0, $8000)
		ENDIF
	FEND

	FUNCTION Size(ptr)
		RESULT = -1
		IF _allocs[ptr, HASH_EXISTS] THEN RESULT = _allocs[ptr]
	FEND

	FUNCTION SetByte(p, data[])
		DEF_DLL RtlMoveMemory(DWORD, BYTE[], DWORD): kernel32
		RESULT = LENGTH(data)
		RtlMoveMemory(p, data, RESULT)
	FEND
	FUNCTION SetDword(p, data)
		DEF_DLL RtlMoveMemory(DWORD, var DWORD, DWORD): kernel32
		RESULT = 4
		RtlMoveMemory(p, data, RESULT)
	FEND
	FUNCTION SetString(p, data, dwFlag=CRYPT_STRING_ASCII, pro=4)
		IFB dwFlag = CRYPT_STRING_ASCII THEN
			RESULT = LENGTHB(data)
			DEF_DLL RtlMoveMemory(DWORD, string, DWORD): kernel32
			RtlMoveMemory(p, data, RESULT)
		ELSE
			RESULT = 0
			DIM sz = 0
			IFB CryptStringToBinaryW(data,0,dwFlag,NULL,sz,NULL,dwFlag) THEN
				IFB p = 0 THEN
					RESULT = Alloc(sz, NULL, pro)
					p = RESULT
				ENDIF
				IF _allocs[p, HASH_EXISTS] AND Size(p) < sz THEN sz = Size(p)
				IF CryptStringToBinaryW(data,0,dwFlag,p,sz,NULL,NULL) AND !RESULT THEN RESULT = sz
			ENDIF
		ENDIF
	FEND

	FUNCTION GetDword(p)
		DEF_DLL RtlMoveMemory(var DWORD, DWORD, DWORD): kernel32
		RESULT = 0
		RtlMoveMemory(RESULT, p, 4)
	FEND
	FUNCTION GetString(addr, size=-1, dwFlag=CRYPT_STRING_ASCII)
		IF size = -1 AND _allocs[addr, HASH_EXISTS] THEN size = _allocs[addr]
		IFB dwFlag = CRYPT_STRING_ASCII THEN
			DEF_DLL RtlMoveMemory(var string, DWORD, DWORD): kernel32
			IFB size >= 0 THEN
				RESULT = FORMAT(CHR(0), size)
				RtlMoveMemory(RESULT, addr, size)
			ELSE
				size = 0
				DIM n = size
				WHILE n = size
					size = size + 1
					RESULT = FORMAT(CHR(0), size)
					RtlMoveMemory(RESULT, addr, size)
					n = LENGTH(RESULT)
				WEND
			ENDIF
			EXIT
		ENDIF
		RESULT = EMPTY
		DIM nstr = 0, str
		IFB CryptBinaryToStringW(addr,size,dwFlag,NULL,nstr) THEN
			str = FORMAT(CHR(0), nstr)
			IFB CryptBinaryToStringW(addr,size,dwFlag,str,nstr) THEN
				RESULT = str
			ENDIF
		ENDIF
	FEND

	PROCEDURE Dump(addr, size=-1, dwFlag=CRYPT_STRING_HEXASCIIADDR)
		PRINT GetString(addr, size, dwFlag)
	FEND

	FUNCTION Import(dllDataB64, funcNameLen=256-PARA_BASE_SIZE)
		DebugLog("Import(, " + funcNameLen + ") start")
		RESULT = Alloc(PARA_BASE_SIZE + funcNameLen)
		IFB RESULT THEN
			DIM dllData = Set(dllDataB64), dllSize = _allocs[dllData], i = 0
			i = i + SetDword(RESULT + i, 0)
			i = i + SetDword(RESULT + i, dllData)
			i = i + SetDword(RESULT + i, dllSize)
			i = i + SetDword(RESULT + i, ELoadDLLResult_OK)
			i = i + SetDword(RESULT + i, _proc)
			i = i + SetDword(RESULT + i, GetProcAddress(hK32, "LoadLibraryA"))
			i = i + SetDword(RESULT + i, GetProcAddress(hK32, "GetProcAddress"))
		ENDIF
		DebugLog("Import(, " + funcNameLen + ") end " + RESULT)
	FEND

	FUNCTION GetFunc(var hDll, funcName)
		DebugLog("GetFunc(" + hDll + ", " + funcName + ") start")
		RESULT = 0
		IF !_allocs[hDll, HASH_EXISTS] THEN EXIT
		DIM size = _allocs[hDll]
		IFB size < PARA_BASE_SIZE + LENGTH(funcName) + 1 THEN
			hDll = Alloc(PARA_BASE_SIZE + LENGTH(funcName) + 1, hDll)
		ENDIF
		DIM first = GetDword(hDll + 44)
		SetDword(hDll, 0)
		SetString(hDll + PARA_BASE_SIZE, funcName + CHR(0))
		DIM type, res = Run(_proc, hDll, type)
		IFB type = 0 AND res = 0 THEN
			RESULT = GetDword(hDll + PARA_FUNC_OFFSET)
			type = GetDword(hDll + 4)
			IFB RESULT > 0 AND type > 0 AND !first THEN
				Free(type)
				SetDword(hDll + 4, 0)
			ENDIF
		ENDIF
		DebugLog("GetFunc(" + hDll + ", " + funcName + ") end " + RESULT)
	FEND

	FUNCTION Call(var hDll, var e, func="", param=0, paramSize=0, dll=EMPTY)
		DebugLog("Call(" + hDll + ", " + e + ", " + func + ", " + param + ", " + paramSize + ", " + dll + ") start")
		RESULT = 0
		e = EMPTY
		DIM hMod = NULL, funcPtr
		DIM bCall = !_allocs[hDll, HASH_EXISTS]
		IFB VARTYPE(param) = VAR_BSTR THEN
			IF _data = NULL THEN _data = Alloc(LENGTHB(param) + 1)
			DIM size = Size(_data)
			IFB LENGTHB(param) + 1 > size THEN
				Free(_data)
				_data = Alloc(LENGTHB(param) + 1)
			ENDIF
			SetString(_data, param + CHR(0))
			param = _data
		ENDIF
		IFB bCall THEN
			IFB dll <> EMPTY THEN
				IFB VARTYPE(dll) <> VAR_BSTR THEN
					hMod = dll
				ELSE
					hMod = LoadLibraryW(dll)
					IFB !hMod THEN
						e = "LoadLibrary fail. " + dll
						EXIT
					ENDIF
				ENDIF
			ENDIF
			hDll = Alloc(PARA_BASE_SIZE + 1)
			IFB !hDll THEN
				e = "Alloc fail."
				EXIT
			ENDIF
			SetDword(hDll + 16, _proc)
		ELSE
			funcPtr = GetDword(hDll + PARA_FUNC_OFFSET)
			IF func <> "" AND (funcPtr = 0 OR GetString(hDll + PARA_BASE_SIZE, LENGTH(func) + 1) <> func) THEN funcPtr = GetFunc(hDll, func)
			IFB funcPtr = 0 THEN
				e = "GetFunc fail."
				EXIT
			ENDIF
		ENDIF
		IF paramSize = -1 AND _allocs[param, HASH_EXISTS] THEN paramSize = Size(param)
		DIM i = 0
		i = i + SetDword(hDll + i, 1)
		i = i + SetDword(hDll + i, param)
		i = i + SetDword(hDll + i, paramSize)
		SetDword(hDll + PARA_LASTERR_OFFSET, GetProcAddress(hK32, "GetLastError"))
		IFB bCall THEN
			IFB hMod <> NULL AND VARTYPE(func) = VAR_BSTR THEN
				i = GetProcAddress(hMod, func)
				IF !i THEN e = "GetProcAddress fail. " + func
			ELSEIF hMod = NULL AND VARTYPE(func) <> VAR_BSTR THEN
				i = func
			ELSE
				e = "Invalid func. " + func
			ENDIF
			SetDword(hDll + PARA_FUNC_OFFSET, i)
		ENDIF
		IFB e = EMPTY THEN
			RESULT = Run(_proc, hDll, i)
			e = GetDword(hDll + PARA_LASTERR_OFFSET)
		ENDIF
		IFB bCall THEN
			IF hMod <> NULL AND hMod <> dll THEN FreeLibrary(hMod)
			Free(hDll)
			hDll = (i = 0)
		ENDIF
		DebugLog("Call(" + hDll + ", " + e + ", " + func + ", " + param + ", " + paramSize + ", " + dll + ") end " + RESULT)
	FEND
	FUNCTION CallEx(var hDll, var e, func=EMPTY, dll=EMPTY, num=0, p0=0, p1=0, p2=0, p3=0, p4=0, p5=0, p6=0, p7=0, p8=0, p9=0, p10=0, p11=0)
		RESULT = CallEx12(hDll, e, func, dll, num, 0, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)
	FEND
	FUNCTION CallEx12(var hDll, var e, func, dll, num, ref, var p0, var p1, var p2, var p3, var p4, var p5, var p6, var p7, var p8, var p9, var p10, var p11)
		DebugLog("CallEx12(" + hDll + ", " + e + ", " + func + ", " + dll + ", " + num + ", " + p0 + ") start")
		DIM paramSize = num * 4, i, p = SAFEARRAY(0, num - 1), f = ref
		FOR i = 0 TO num - 1
			p[i] = EVAL("p" + i)
			IF VARTYPE(p[i]) = VAR_BSTR THEN paramSize = paramSize + LENGTHB(p[i]) + 1
			IF f MOD 2 THEN paramSize = paramSize + 4
			f = INT(f / 2)
		NEXT
		DIM param = Alloc(paramSize), offset = num * 4
		f = ref
		FOR i = 0 TO num - 1
			IFB VARTYPE(p[i]) = VAR_BSTR THEN
				SetDword(param + i * 4, param + offset)
				SetString(param + offset, p[i] + CHR(0))
				offset = offset + LENGTHB(p[i]) + 1
			ELSEIF f MOD 2 THEN
				SetDword(param + i * 4, param + offset)
				SetDword(param + offset, p[i])
				offset = offset + 4
			ELSE
				SetDword(param + i * 4, p[i])
			ENDIF
			f = INT(f / 2)
		NEXT
		RESULT = Call(hDll, e, func, param, paramSize, dll)

		offset = num * 4
		f = ref
		FOR i = 0 TO num - 1
			IFB VARTYPE(p[i]) = VAR_BSTR THEN
				EVAL("p" + i + ":=<#DBL>" + GetString(param + offset) + "<#DBL>")
				offset = offset + LENGTHB(p[i]) + 1
			ELSEIF f MOD 2 THEN
				EVAL("p" + i + ":=" + GetDword(param + offset))
				offset = offset + 4
			ENDIF
			f = INT(f / 2)
		NEXT
		Free(param)
		DebugLog("CallEx12(" + hDll + ", " + e + ", " + func + ", " + dll + ", " + num + ", " + p0 + ") end " + RESULT)
	FEND
	FUNCTION CallEx6(var hDll, var e, func, dll, num, ref, var p0, var p1, var p2, var p3, var p4, var p5)
		DIM p6, p7, p8, p9, p10, p11
		RESULT = CallEx12(hDll, e, func, dll, num, ref, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)
	FEND

	FUNCTION Unload(hDll)
		DebugLog("Unload(" + hDll + ") start")
		SetDword(hDll, 2)
		DIM type
		RESULT = Run(_proc, hDll, type)
		Free(hDll)
		DebugLog("Unload(" + hDll + ") end " + RESULT)
	FEND

	FUNCTION FormatMessage(msgId, langId=0)
		DebugLog("FormatMessage(" + msgId + ", " + langId + ") start")
		RESULT = msgId
		DIM p = 256, i = p, ret, e = 0, wk = Alloc(2048)
		WHILE i >= p - 1 AND e = 0
			p = p * 2
			IFB p > Size(wk) THEN
				Free(wk)
				wk = Alloc(p)
			ENDIF
			i = CallEx(ret, e, "FormatMessageA", "kernel32", 7, $1200, 0, msgId, langId, wk, p, 0)
		WEND
		IFB wk AND e = 0 THEN
			RESULT = GetString(wk, i)
			Free(wk)
		ENDIF
		DebugLog("FormatMessage(" + msgId + ", " + langId + ") end " + RESULT)
	FEND

	FUNCTION ReadFromFile(path)
		DebugLog("ReadFromFile(" + path + ") start")
		RESULT = 0
		DIM ret, e, read, size
		DIM hFile = CallEx(ret, e, "CreateFileA", hK32, 7, path, $80000000, 1, 0, 3, 0, 0)
		IF hFile = $FFFFFFFF THEN PRINT "CreateFile失敗:" + FormatMessage(e)
		IFB CallEx6(ret, e, "GetFileSizeEx", hK32, 3, 6, hFile, size, read, 0, 0, 0) AND read = 0 THEN
			RESULT = Alloc(size)
			IFB !CallEx6(ret, e, "ReadFile", hK32, 5, 8, hFile, RESULT, size, read, 0, 0) OR !ret THEN
				PRINT "ReadFile失敗:" + FormatMessage(e)
				Free(RESULT)
				RESULT = 0
			ENDIF
		ELSEIF read > 0 THEN
			PRINT "ファイルサイズが大きすぎます " + (read * $100000000 + size)
		ELSE
			PRINT "GetFileSize失敗:" + FormatMessage(e)
		ENDIF
		CloseHandle(hFile)
		DebugLog("ReadFromFile(" + path + ") end " + RESULT)
	FEND


	PROCEDURE DebugLog(msg)
		IF Debug THEN PRINT msg
		IF Debug > 1 THEN MSGBOX(msg)
	FEND


	TEXTBLOCK _dll_imp_code
		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
		DQAAAABfXluL5V3D
	ENDTEXTBLOCK

ENDMODULE

テストコードにある、_mini_dllは、ログ出力用の簡単なDLL。
OpenLog関数で指定したファイルに、日時でLog出力します。
LogPut関数は第二引数に数値を取り、指定書式で出力します。


Asmモジュールの機能を内包しました。
DLLをロードするだけで、ここまで巨大になってしまうとは、、、。
ただし、Asmモジュールほどでないにしても、埋め込むDLLに制約があります。


Asmモジュールを内包した都合上、API呼び出しをCall関数にしました。
また、Win32API呼び出しとスクリプト埋め込みDLLの呼び出しI/Fを共通化しました。
API呼び出しは、少しだけ簡単なようにしました。


これで、1ファイルでかなりのことができるようになった気がする、、、。
スクリプトが莫大になるけど。
でも、しろまささんのところにあった、Module_ChkCtlID.uwsはインプリメントできない。
多分、HMODULEとして使えないのが原因。

使い方

  1. DLLをBase64エンコードし、TEXTBLOCKに定義する
    1. 呼べるDLLには制約がありますが、、、Base64変換は以下の通り
    2. tar=Dll.ReadFromFile(対象);PRINT Dll.GetString(tar,-1,1);Dll.Free(tar)
  2. Dll.ImportにTEXTBLOCKの内容を渡す
  3. インプリメントしたDLLの関数を呼びだす
    1. 引数が4Byteの数値か、文字列のポインターの場合は、Dll.Callで呼ぶ
      1. 第一引数、Dll.Importのリターン
      2. 第二引数、GetLastErrorを受け取る変数(主にWin32API用)
      3. 第三引数、呼び出す関数名
      4. 第四引数、省略可。関数に渡すパラメーター
      5. 関数に渡すパラメーターが12を超える場合は、メモリー確保してこれを呼ぶ
    2. 引数が4Byteを超える場合は、Dll.CallExで呼ぶ
      1. 第一引数、Dll.Importのリターン
      2. 第二引数、GetLastErrorを受け取る変数(主にWin32API用)
      3. 第三引数、呼び出す関数名(ここまで上と同じ)
      4. 第四引数、EMPTY固定(Win32API用DLL指定)
      5. 第五引数、関数に渡すパラメーターの数
      6. 第六引数〜、渡すパラメーター。数値はそのまま、文字列なら確保してポインターを渡す
    3. 引数で戻りを受けたい場合は、Dll.CallEx12またはDll.CallEx6を呼ぶ(引数の数の差)
      1. 第一引数、Dll.Importのリターン
      2. 第二引数、GetLastErrorを受け取る変数(主にWin32API用)
      3. 第三引数、呼び出す関数名
      4. 第四引数、EMPTY固定(Win32API用DLL指定)
      5. 第五引数、関数に渡すパラメーターの数(ここまで上と同じ)
      6. 第六引数、参照ビットフラグ
        1. 第一パラメーターをポインターにするなら、最下位ビット。第二パラメーターならその上のビット、、、
        2. Dll.ReadFromFileのGetFileSizeExは、第二と第三なので 110=6。ReadFileは、第四なので 1000=8
      7. 第七引数〜、渡すパラメーター。数値でも参照ビットが立っていればポインターに立ってなければそのまま、文字列ならポインターを渡す
    4. リターンはDWORDとみなされるので、intの場合は注意($80000000以上の場合は$100000000を引く)
  4. インプリメントしたDLLを使い終わったら、Dll.Unloadを呼ぶ
    1. 呼ばないとメモリーリークの元(プロセス終了で通常解放されるけど)
  5. 最後にDll.Disposeを呼ぶ
    1. 手動でAllocしたメモリーを全てFreeしていれば不要だけど、まとめて解放してくれる
    2. ImportしたDLLをUnloadはしてくれないので、注意(改造すべき?)

インプリメント可能なDLLの制約について

参照先にあるように、以下のような制約があります。
適当に日本語訳してみました。

  1. ロードされたDLLはHMODULEを持たないから、リソースを使うのはつらい
  2. DllMainはスレッドのアタッチ・デタッチでは呼ばれない
  3. ロードされたDLLから他DLLの呼び出しにLoadLibraryを使ってるからkernel32非依存だとクラッシュ
    1. UWSCはkernel32依存なので問題とはなりません
  4. 例外処理機構(__tryブロック)は多分機能しない(HMODULEを持たないことに起因?)
  5. CRTは簡単なものを除き上手く動作しない
    1. インプリメントするDLLは、/NODEFAULTLIBして作った方が良い(エントリーポイントの指定を忘れずに)