hi all,
I've had some things that did not find resolved, so I want to discuss it with my teachers in this forum
I beat most of the problems of consensus between the .net and Masm, except for certain things, such as the problem of passing an argument of type system.IntPtr.
Any variable sends to/returne from .net method is a ptr to VARIANT,we can send any type without problems, but an exception (HRESULT: 80131604) has been thrown while using IntPtr Transformation
________
__Exept : [80131604]
__Method: [Void TestIntPtr(IntPtr)]
__Object: STATIC [0]
___________
this documentation (https://msdn.microsoft.com/en-us/library/2x07fbw8%28v=vs.110%29.aspx#cpcondefaultmarshalingforobjectsanchor3)explain how to marshal any object, it sed that IntPtr transform to variant of type VT_INT
My Helper (masm32ref (http://sourceforge.net/projects/masm32ref/files/)) lets you insert an .net code (vb/csharp/JavaS) inside masm program, So I've created a program (Attachment) to illustrate the problem and help to resolve it,
I insert cs code, one static class with 5 function, the first is an empty proc by 1 arg (intptr) , just to facilitate the search for a solution
public static void TestIntPtr(System.IntPtr iptr) { }
the second and the therd is the same proc, with diference argument, Fourth and fifth is the same proc, with difirent arg, and There are also other method to try
the sc code is compiled at runtim to tomporary dll,to use it as .net assembly
you can assembly by hjwasm a plase the ml
here are other people suffering from the problem of sending IntPtr :
Passing unmanaged handle to managed IntPtr via COM (https://social.msdn.microsoft.com/Forums/vstudio/en-US/3591cce9-e0f1-4c4e-8ad3-5952e9114ede/passing-unmanaged-handle-to-managed-intptr-via-com?forum=clr)
Passing IntPtr through COM interop (http://stackoverflow.com/questions/16825529/passing-intptr-through-com-interop)
Can't invoke a COM visible method with IntPtr parameter. (https://social.msdn.microsoft.com/Forums/vstudio/en-US/1854db80-12c5-4f14-ad92-f3b274805a4d/cant-invoke-a-com-visible-method-with-intptr-parameter?forum=clr)
https://msdn.microsoft.com/en-us/library/system.intptr%28v=vs.110%29.aspx (https://msdn.microsoft.com/en-us/library/system.intptr%28v=vs.110%29.aspx)
Quote from: dedndave on February 13, 2016, 08:46:29 AM
https://msdn.microsoft.com/en-us/library/system.intptr%28v=vs.110%29.aspx (https://msdn.microsoft.com/en-us/library/system.intptr%28v=vs.110%29.aspx)
dave
The problem is how to pass a variable of type
System.IntPtr to .net methods
This link speaks in detail on the subject https://msdn.microsoft.com/en-us/library/2x07fbw8%28v=vs.110%29.aspx (https://msdn.microsoft.com/en-us/library/2x07fbw8%28v=vs.110%29.aspx)
All types work well, but there are some species types that need special treats, like
System.Decimal convert to Variant type
VT_DECIMAL, but using the full variant
Quote
VARIANT STRUCT
wReserved SWORD VT_DECIMAL
UNION
signscale SWORD ?
STRUCT
scale BYTE ? ; Power of 10
sign BYTE ? ; FALSE/TRUE (0,-1)
ENDS
ends
Hi32 SDWORD ?
UNION
Lo64 QWORD ?
STRUCT
Lo32 SDWORD ?
Mid32 SDWORD ?
ENDS
ends
VARIANT ENDS
Also VT_RECORD using last QWORD of variant as 2 dword
Quote
VARIANT STRUCT
vt WORD VT_RECORD
wReserved1 WORD 0
wReserved2 WORD 0
wReserved3 WORD 0
pvRecord DWORD ?
pRecInfo DWORD ?
VARIANT ENDS
As for type
IntPtr I could not find a solution
usually, API functions would receive a pointer to the structure
however, in the world of COM, they sometimes pass the entire structure
for VARIANT types, i find it's easier to work with (in ASM) if you prototype the functions with 4 DWORD's
for example...
;IUnknown interface vTable (structure)
IUnknown STRUCT
METHOD(QueryInterface, _this:LPVOID,riid:LPVOID,ppvObj:LPVOID)
METHOD(AddRef, _this:LPVOID)
METHOD(Release, _this:LPVOID)
IUnknown ENDS
;IDispatch interface vTable (structure)
IDispatch STRUCT
IUnknown <>
METHOD(GetTypeInfoCount, _this:LPVOID,pctinfo:LPVOID)
METHOD(GetTypeInfo, _this:LPVOID,iTInfo:UINT,lcid:LCID,ppTInfo:LPVOID)
METHOD(GetIDsOfNames, _this:LPVOID,riid:LPVOID,rgszNames:LPOLESTR,cNames:UINT,lcid:LCID,rgDispId:LPVOID)
METHOD(dInvoke, _this:LPVOID,dispIdMember:DWORD,riid:LPVOID,lcid:LCID,wFlags:DWORD,pDispParams:LPVOID,pVarResult:LPVOID,pExcepInfo:LPVOID,puArgErr:LPVOID)
IDispatch ENDS
;IShellDispatch interface vTable (structure)
; vDir VARIANT struct = vtDir:DWORD,vD0:DWORD,vstrDir:LPVOID,vDV0:DWORD
;vRootFolder VARIANT struct = vtRoot:DWORD,vR0:DWORD,vstrRoot:LPVOID,vRV0:DWORD
IShellDispatch STRUCT
IDispatch <>
METHOD(Application, _this:LPVOID,ppid:LPVOID)
METHOD(Parent, _this:LPVOID,ppid:LPVOID)
METHOD(NameSpace, _this:LPVOID,vtDir:DWORD,vD0:DWORD,vstrDir:LPVOID,vDV0:DWORD,ppsdf:LPVOID)
METHOD(BrowseForFolder, _this:LPVOID,Hwnd:DWORD,lpTitle:LPVOID,Options:DWORD,vtRoot:DWORD,vR0:DWORD,vstrRoot:LPVOID,vRV0:DWORD,ppsdf:LPVOID)
METHOD(Windows, _this:LPVOID,ppid:LPVOID)
METHOD(Open, _this:LPVOID,vtDir:DWORD,vD0:DWORD,vstrDir:LPVOID,vDV0:DWORD)
METHOD(Explore, _this:LPVOID,vtDir:DWORD,vD0:DWORD,vstrDir:LPVOID,vDV0:DWORD)
METHOD(MinimizeAll, _this:LPVOID)
METHOD(UndoMinimizeALL, _this:LPVOID)
METHOD(FileRun, _this:LPVOID)
METHOD(CascadeWindows, _this:LPVOID)
METHOD(TileVertically, _this:LPVOID)
METHOD(TileHorizontally, _this:LPVOID)
METHOD(ShutdownWindows, _this:LPVOID)
METHOD(Suspend, _this:LPVOID)
METHOD(EjectPC, _this:LPVOID)
METHOD(SetTime, _this:LPVOID)
METHOD(TrayProperties, _this:LPVOID)
METHOD(Help, _this:LPVOID)
METHOD(FindFiles, _this:LPVOID)
METHOD(FindComputer, _this:LPVOID)
METHOD(RefreshMenu, _this:LPVOID)
METHOD(ControlPanelItem, _this:LPVOID,bstrDir:LPVOID)
now let me find out about IntPtr
i think it's a single DWORD for 32-bit code (QWORD for 64-bit)
oh ok
it's a VARIANT structure - do what i did, it will make life easier :t
dave
This is the way to call .net methods, Any method in .net: MethodBase.Invoke Method (Object, BindingFlags, Binder, Object[], CultureInfo) (https://msdn.microsoft.com/en-us/library/4k9x6bc0(v=vs.110).aspx)
I translate it to be available to users of Masm in DotNetHelper.inc:
__Private_BasicInvoke proc c uses ECX EDX ebx ESI EDI ParamsCount:dword,mtd__:DWORD,Object__:DWORD,lpRetVal,Params:VARARG
LOCAL __hParam,exept_
LOCAL P_data:DWORD
LOCAL __InvokevtMethod :VARIANT
LOCAL __Exc_MethodStr :VARIANT
LOCAL __Exc_ObjectStr :VARIANT
.data
__ParamInvokeSAFEARRAY SAFEARRAY <>
__BasicInvokeSAFEARRAY SAFEARRAY <>
__InvokepvData VARIANT 2 dup(<>)
__InvokevtRetValue VARIANT <>
.code
.if !ParamsCount
xor EAX, EAX
mov edx, [ebp+4]
cmp WORD PTR[edx], 0C483h
jne @F
MOVZX EAX, BYTE PTR [EDX+2]
SHR EAX, 2
SUB eax,4
MOV ParamsCount,eax
@@:
.endif
.IF !__Basic_Invoke
CALL __Private_GetBasicMethods
.ENDIF
.IF __Basic_Invoke
.IF ParamsCount
MOV EAX,16
MOV ECX,ParamsCount
Mul ECX
MOV ECX,EAX
invoke CoTaskMemAlloc ,ECX
MOV P_data,EAX
MOV EDI,EAX
MOV ECX,ParamsCount
xor EDX,edx
@@:
cmp ECX,edx
je @F
PUSH ECX
PUSH EDX
;---------------------
MOV ECX, Params[EDX*4]
.IF ECX
INVOKE RtlMoveMemory,EDI,ECX,16
.ELSE
INVOKE RtlZeroMemory,EDI,SIZEOF VARIANT
.ENDIF
ADD EDI,16
;---------------------
POP EDX
POP ECX
inc EDX
jmp @B
@@:
.ELSE
MOV P_data,FALSE
.ENDIF
LEA ECX,__ParamInvokeSAFEARRAY
MOV [ECX].SAFEARRAY.cDims ,1
MOV [ECX].SAFEARRAY.fFeatures ,0
MOV [ECX].SAFEARRAY.cbElements ,16
MOV [ECX].SAFEARRAY.cLocks ,0
m2m [ECX].SAFEARRAY.pvData ,P_data
MOV EAX,ParamsCount
MOV [ECX].SAFEARRAY.rgsabound.cElements ,EAX
MOV [ECX].SAFEARRAY.rgsabound.lLbound ,0
LEA ECX,__BasicInvokeSAFEARRAY
MOV [ECX].SAFEARRAY.cDims ,1
MOV [ECX].SAFEARRAY.fFeatures ,0
MOV [ECX].SAFEARRAY.cbElements ,16
MOV [ECX].SAFEARRAY.cLocks ,0
LEA EAX,__InvokepvData
m2m [ECX].SAFEARRAY.pvData ,EAX
MOV EAX,ParamsCount
MOV [ECX].SAFEARRAY.rgsabound.cElements ,2
MOV [ECX].SAFEARRAY.rgsabound.lLbound ,0
LEA EDI,__InvokepvData
.IF Object__
INVOKE RtlMoveMemory,EDI,Object__,SIZEOF VARIANT
.ELSE
INVOKE RtlZeroMemory,EDI,SIZEOF VARIANT
.ENDIF
ADD EDI,SIZEOF VARIANT
MOV [EDI].VARIANT.vt,0200CH
LEA EAX,__ParamInvokeSAFEARRAY
m2m [EDI].VARIANT.parray,EAX
MOV cx,__vtOfMethods
MOV __InvokevtMethod.vt,cx
PUSH mtd__
POP __InvokevtMethod.punkVal
LEA EAX,__InvokevtRetValue
PUSH EAX
LEA EAX ,__BasicInvokeSAFEARRAY
PUSH EAX
LEA EDI,__InvokevtMethod
PUSH DWORD PTR [EDI+12]
PUSH DWORD PTR [EDI+8]
PUSH DWORD PTR [EDI+4]
PUSH DWORD PTR [EDI]
MOV EDX, __Basic_Invoke
PUSH EDX
MOV EDX,[EDX]
CALL DWORD PTR [EDX+148]
.IF !EAX
.IF lpRetVal
INVOKE RtlMoveMemory,lpRetVal,addr __InvokevtRetValue,SIZEOF VARIANT
MOV EAX,lpRetVal
.ENDIF
MOV EAX,TRUE
.ELSE
mov exept_,eax
.data
__pInvoke_ErrBuf db 128*2*3 dup(?)
.code
invoke RtlZeroMemory,addr __pInvoke_ErrBuf,128*2*3
invoke lstrcat,addr __pInvoke_ErrBuf,BSTR$(13,10,"___________",13,10,"__Exept : [")
invoke lstrcat,addr __pInvoke_ErrBuf,_rv(__Hex,exept_)
invoke lstrcat,addr __pInvoke_ErrBuf,BSTR$("]")
LEA EAX,__Exc_MethodStr
PUSH EAX
LEA EAX,__InvokevtMethod
PUSH EAX
CALL __Private_BasicToString
.IF EAX
invoke lstrcat,addr __pInvoke_ErrBuf,BSTR$(13,10,"__Method: [")
invoke lstrcat,addr __pInvoke_ErrBuf,__Exc_MethodStr.punkVal
.ELSE
invoke lstrcat,addr __pInvoke_ErrBuf,BSTR$(13,10,"__Method: [?")
.ENDIF
invoke lstrcat,addr __pInvoke_ErrBuf,BSTR$("]")
.IF Object__
LEA EAX,__Exc_ObjectStr
PUSH EAX
PUSH Object__
CALL __Private_BasicToString
.IF EAX
invoke lstrcat,addr __pInvoke_ErrBuf,BSTR$(13,10,"__Object: [")
invoke lstrcat,addr __pInvoke_ErrBuf,__Exc_ObjectStr.punkVal
invoke lstrcat,addr __pInvoke_ErrBuf,BSTR$("]")
.ELSE
invoke lstrcat,addr __pInvoke_ErrBuf,BSTR$(13,10,"__Object: [???] ")
.ENDIF
.ELSE
invoke lstrcat,addr __pInvoke_ErrBuf,BSTR$(13,10,"__Object: STATIC [0] ")
.ENDIF
invoke lstrcat,addr __pInvoke_ErrBuf,BSTR$(13,10,"___________")
__ExeptionMsg addr __pInvoke_ErrBuf
MOV EAX,FALSE
.ENDIF
PUSH EAX
.IF ParamsCount
invoke CoTaskMemFree,P_data
.ENDIF
POP EAX
.ELSE
MOV EAX,FALSE
.ENDIF
ret
__Private_BasicInvoke ENDP
see : object[] parameters; Is a array (SAFEARRAY) of the VARIANT, Any argument must be in the form of a VARIANT to pass.