diff --git a/Core/DolphinVM/ExternalCall.asm b/Core/DolphinVM/ExternalCall.asm index d45cd6be5a..a0392eebc0 100644 --- a/Core/DolphinVM/ExternalCall.asm +++ b/Core/DolphinVM/ExternalCall.asm @@ -54,6 +54,9 @@ extern CharacterGetCodePoint:near32 ; We need to test the structure type specially ArgSTRUCT EQU 50 +getDllCallAddress EQU ?GetDllCallProcAddress@Interpreter@@CIP6GHXZPAUExternalMethodDescriptor@DolphinX@@I@Z +extern getDllCallAddress:near32 + atoi PROTO C :DWORD GetProcAddress PROTO STDCALL :HINSTANCE, :LPCSTR @@ -255,7 +258,7 @@ performCall: ret ; eax will be non-zero as otherwise we'd not be here procAddressNotCached: - call getProcAddress ; Cache value 0, so lookup the proc address + call getDllCallAddress ; Cache value 0, so lookup the proc address test eax, eax ; Returns null if not a valid proc name jnz performCall @@ -267,46 +270,6 @@ procAddressNotCached: asyncDLL32Call ENDP -getProcAddress PROC - ASSUME ecx:PTR CallDescriptor ; ecx points at descriptor bytes - - push ebx ; Save EBX - mov ebx, ecx ; Save for later in safe register - ASSUME ebx:PTR CallDescriptor ; ebx now points at descriptor bytes - ASSUME ecx:NOTHING ; Now free to re-use ECX - - ; Get receiver from under args and extract the handle - mov eax, _SP - lea ecx, [edx*OOPSIZE] ; Offset of receiver down stack - sub eax, ecx ; eax now points at receiver in stack - - ; Get address of proc name in the descriptor into eax - ; N.B. Arg Count cannot be greater than 255 - mov dl, [ebx].m_argsLen - lea edx, DWORD PTR [ebx].m_args[edx] - - mov eax, [eax] ; Load receiver Oop from stack - mov eax, (OTE PTR[eax]).m_location - mov eax, (ExternalLibrary PTR[eax]).m_handle ; Get handle Oop from receiver - mov eax, (OTE PTR[eax]).m_location - - ; Prepare for call to GetProcAddress - push edx ; Push address of proc name - push (ExternalHandle PTR[eax]).m_handle ; Push DLL handle for call to GetProcAddress - - INVOKE atoi, edx - - test eax, eax ; atoi() returned 0? - jz @F ; Yes, not an ordinal - mov [esp+4], eax ; Store down ordinal value instead - -@@: - call GetProcAddress - mov [ebx].m_proc, eax ; Save down into cache - pop ebx ; restore EBX - ret ; Proc address in EAX -getProcAddress ENDP - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; A fastcall function (ecx is pMethod, edx is argCount) BEGINPRIMITIVE primitiveDLL32Call @@ -341,7 +304,7 @@ performCall: ret procAddressNotCached: - call getProcAddress ; Cache value 0, so lookup the proc address + call getDllCallAddress ; Cache value 0, so lookup the proc address test eax, eax ; Returns null if not a valid proc name jnz performCall diff --git a/Core/DolphinVM/Interprt.h b/Core/DolphinVM/Interprt.h index 7487a2942c..21b0c7b7f6 100644 --- a/Core/DolphinVM/Interprt.h +++ b/Core/DolphinVM/Interprt.h @@ -758,11 +758,12 @@ class Interpreter private: static BOOL __stdcall callExternalFunction(FARPROC pProc, argcount_t argCount, DolphinX::CallDescriptor* argTypes, BOOL isVirtual); - + static FARPROC GetDllCallProcAddress(DolphinX::ExternalMethodDescriptor* descriptor, size_t argCount); + // Pushs object on stack instantiated from address, and returns size of object pushed static void pushArgsAt(CallbackDescriptor* descriptor, argcount_t argCount, uint8_t* lpParms); static argcount_t pushArgsAt(const ExternalDescriptor* descriptor, uint8_t* lpParms); - + static void failTrace(); public: diff --git a/Core/DolphinVM/STExternal.h b/Core/DolphinVM/STExternal.h index b821b2c21c..edd2884c10 100644 --- a/Core/DolphinVM/STExternal.h +++ b/Core/DolphinVM/STExternal.h @@ -22,10 +22,12 @@ namespace ST class ExternalStructure; class ExternalAddress; class ExternalHandle; + class ExternalLibrary; } typedef TOTE StructureOTE; typedef TOTE AddressOTE; typedef TOTE HandleOTE; +typedef TOTE LibraryOTE; struct COMThunk { @@ -105,6 +107,13 @@ namespace ST OTE* m_literals[]; }; + class ExternalLibrary : public Object + { + public: + HandleOTE* m_handle; + }; + + /////////////////////////////////////////////////////////////////////////////// // Answer either a SmallInteger or an ExternalHandle (if too big) to hold diff --git a/Core/DolphinVM/extcall.cpp b/Core/DolphinVM/extcall.cpp index 73da36c539..c5df2dabbc 100644 --- a/Core/DolphinVM/extcall.cpp +++ b/Core/DolphinVM/extcall.cpp @@ -218,6 +218,25 @@ BytesOTE* __fastcall NewGUID(GUID* rguid) return ObjectMemory::newByteObject(Pointers.ClassGUID, sizeof(GUID), rguid); } +FARPROC Interpreter::GetDllCallProcAddress(DolphinX::ExternalMethodDescriptor* descriptor, size_t argCount) +{ + Oop* sp = m_registers.m_stackPointer; + LibraryOTE* oteReceiver = reinterpret_cast(*(sp - argCount)); + HMODULE hModule = static_cast(oteReceiver->m_location->m_handle->m_location->m_handle); + + LPCSTR procName = reinterpret_cast(descriptor->m_descriptor.m_args + descriptor->m_descriptor.m_argsLen); + int ordinal = atoi(procName); + if (ordinal != 0) + { + procName = reinterpret_cast(ordinal); + } + + FARPROC proc = ::GetProcAddress(hModule, procName); + descriptor->m_proc = proc; + + return proc; +} + /////////////////////////////////////////////////////////////////////////////// // argcount_t Interpreter::pushArgsAt(const ExternalDescriptor* descriptor, uint8_t* lpParms)