News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Masm32Ref

Started by mabdelouahab, January 14, 2016, 09:56:41 AM

Previous topic - Next topic

jj2007

Quote from: mabdelouahab on June 12, 2016, 02:39:29 AM
Jochen, Don't forget that the third line in ComHelper.inc is
Quote__UNICODE__    equ   1

... and chr$() becomes uni$()? I was not aware of that feature, thanks for informing me :(

Zen

#46
EDIT: For those of you that are looking for information about MASMRef, ignore the following post. I have made a HUGE, INCREDIBLY STUPID blunder here. I'm actually quite embarrassed. :dazzled: The LoadLibrary call that I describe below, actually works perfectly. I apologize to MABDELOUAHAB. But, I've left the original post here, so that you can have a good laugh. :bgrin:

MABDELOUAHAB,
Hi, again. I've started writing a long procedure to create the BSTRs (with SysAllocString) that DotNetHelper.inc requires. Also, I've been modifying DotNetHelper.inc just to see what's working. So, naturally, I invoked __InitCLR, since it starts the whole .NET Framework Hosting. As you know, it calls a number of other routines in DotNetHelper.inc (__Private_MsCorEE, __Private_GetRuntimeHost2 , __Private_GetRuntimeHost4 , and, __ForEachInstalledRuntimes). In __Private_MsCorEE, the code calls LoadLibrary like this:   

.IF !hMsCorEE
invoke LoadLibrary,BSTR$("mscoree")
MOV hMsCorEE ,EAX
.ENDIF


This call FAILS,...so, hMsCorEE is NULL. Consequently, everything else in __Private_MsCorEE fails to execute.

In the modified version that I'm testing, I simply use a normal ascii string in a .data section:
.data
szMSCore BYTE "mscoree.dll", 0   

...and call LoadLibrary like this:
invoke LoadLibrary, ADDR szMSCore    ;    Modified from original   
;    If the LoadLibrary function fails, the return value is NULL.     
                        mov hMsCorEE, eax   
                        .IF eax==NULL    ;    Modified from original (Added this Log File notification if LoadLibrary fails.)   
                        invoke LogEntry, ADDR szFAILLoadLib   
                        RET
                       .ENDIF


LogEntry is just a function that writes some data to a Log File, in this case: szFAILLoadLib BYTE "LoadLibrary FAILED for mscoree.dll.", 0Dh, 0Ah, 0

jj2007

LoadLibraryW will work.

Zen

#48
EDIT: Ok,...I go into more detail here with my demented LoadLibrary complaint. It's ridiculous at this point, so,...I've deleted the original post. :bgrin:

...And, oh, yes,...another apology to MABDELOUAHAB. :dazzled:

mabdelouahab

Zen
I made the DotNetHelper.inc in order to have the first file include, This means that if other files are included, so you should understand that all functions are designed to work with   __UNICODE__ 

Quote
.IF !hMsCorEE
   invoke LoadLibraryW,BSTR$("mscoree")
   MOV hMsCorEE   ,EAX
.ENDIF
OR

Quote
.IF !hMsCorEE
   invoke LoadLibrary,chr$("mscoree")
   MOV hMsCorEE   ,EAX
.ENDIF



Zen

#50
MABDELOUAHAB,
Oh, sorry. (I must have been drunk :bgrin:)

Zen

Hi, MABDELOUAHAB,
Well,...I've been working through your code,...and I have a question. It's a long and involved question,...and, I'm kind of reluctant to ask, because of the LoadLibrary debacle above. :bgrin:
...Anyway, the question involves some code at the end of the function: __Private_GetRuntimeHost4, which is called from both, __InitCLR, and __GetDefaultDomain. In my Test App, I have a function, activated by a menu selection that just calls __InitCLR. It seems to work fine (I modified the code somewhat, and added numerous comments for English-speaking .NET Framework enthusiasts). I'm sure that you are familiar with the __Private_GetRuntimeHost4 function,...it basically obtains a number of COM interfaces that are necessary to load and initialize the .NET Framework CLR Version 4.
Here is the original version of __Private_GetRuntimeHost4 from DotNetHelper.inc:

__Private_GetRuntimeHost4 PROC
.IF !Curr_CLRRuntimeInfo
.IF !Curr_CLRMetaHost
    invoke CLRCreateInstance,addr CLSID_CLRMetaHost,addr IID_ICLRMetaHost,addr Curr_CLRMetaHost
.ENDIF
.IF Curr_CLRMetaHost
MOV Curr_CLRRuntimeInfo,0
PUSH 0
PUSH offset CallBackFunction_GetLastVersionInstaled
CALL __ForEachInstalledRuntimes
.ENDIF
.ENDIF
.IF Curr_CLRRuntimeInfo
        PUSH OFFSET Curr_CLRRuntimeHost
        PUSH OFFSET IID_ICLRRuntimeHost
        PUSH OFFSET CLSID_CLRRuntimeHost
        MOV EDX , Curr_CLRRuntimeInfo
        PUSH EDX   
        MOV EDX ,[EDX]   
        CALL DWORD PTR [EDX+36]
.IF !EAX
MOV EDX, Curr_CLRRuntimeHost
        PUSH EDX   
        MOV EDX,[EDX]   
        CALL DWORD PTR [EDX+12]
PUSH OFFSET Curr_CorRuntimeHost
        PUSH OFFSET IID_ICorRuntimeHost
        PUSH OFFSET CLSID_CorRuntimeHost
        MOV EDX , Curr_CLRRuntimeInfo
        PUSH EDX   
        MOV EDX ,[EDX]   
        CALL DWORD PTR [EDX+36]
.IF !eax
MOV EAX,TRUE
.ELSE
MOV EAX,FALSE
.ENDIF
.ELSE
MOV EAX,FALSE
.ENDIF

.ELSE
MOV EAX,FALSE
.ENDIF
ret
__Private_GetRuntimeHost4 endp


So,...here is the question: After loading the Common Language Runtime (CLR) version 4, and calling ICLRRuntimeHost:Start (which succeeds), you have a block of code that calls ICLRRuntimeInfo:GetInterface (using the ICLRRuntimeInfo interface pointer for version 4) to obtain an ICorRuntimeHost interface pointer. Why ??? The documentation for the ICorRuntimeHost interface states that: "In the .NET Framework version 2.0, this interface is superseded by ICLRRuntimeHost." I'm just wondering if this is necessary.
See, Deprecated CLR Hosting Functions

...By the way,...you can run this code in Process Explorer, and you can actually watch CLR.DLL load into the Test App's address space when the __InitCLR function executes. So, it works, no question. :bgrin:

mabdelouahab

Hi Zen
Quote from: Zen on June 21, 2016, 06:07:23 AM
So,...here is the question: After loading the Common Language Runtime (CLR) version 4, and calling ICLRRuntimeHost:Start (which succeeds), you have a block of code that calls ICLRRuntimeInfo:GetInterface (using the ICLRRuntimeInfo interface pointer for version 4) to obtain an ICorRuntimeHost interface pointer. Why ??? The documentation for the ICorRuntimeHost interface states that: "In the .NET Framework version 2.0, this interface is superseded by ICLRRuntimeHost." I'm just wondering if this is necessary.
Yes it is necessary, we must obtain an ICorRuntimeHost interface pointer to get the DefaultDomain
If you work for load CLR v1/v1.1/v2, you can obtain an ICorRuntimeHost interface pointer when you execute the function CorBindToRuntimeEx
but if  you work for load CLR v4, you should start with CLRCreateInstance Function because this function supersedes all the CorBindTo* functions listed in the .NET Framework 1.1 and 2.0 Hosting Global Static Functions, after you call this function you can obtain an ICLRMetaHost interface pointer, then call GetRuntime to obtain an ICLRRuntimeInfo interface pointer, then call GetInterface  to obtain an ICorRuntimeHost interface pointer

Zen

Thanks, MABDELOUAHAB,
So,...the only way in is the AppDomain Class ???
...And, the only way to obtain access to the AppDomain Class is through the ICorRuntimeHost Interface ???

mabdelouahab

Update:
    - added a file wStrings.inc, contains all the text strings used by DotNetHelper.inc (Placed in: \masm32\include)
    - added __Private_LoadMsCoreE proc to DotNetHelper.inc, to load MsCoreE library (x86/x64 OS)

Zen

#55
Hi, again MABDELOUAHAB,
Thanks for the update. I've read the new files.
I've got another question (and this one is more annoying than all the others  :bgrin:).
I'm slowly and meticulously going through the code in the procedure: __GetDefaultDomain, and, I notice that you are calling interface methods of the AppDomain instance that represents the default application domain for the process, retrieved from ICorRuntimeHost:GetDefaultDomain (IID_AppDomain).
For example (from __ForEachAssemblyInIAppDomain):
.IF _rv(__InitCLR)
LEA ECX,Asm__s    ;    Asm__s is defined as a LOCAL variable
PUSH ECX
.IF IAppDom    ;    IAppDom is a parameter of __ForEachAssemblyInIAppDomain, which in this case is zero.   
        MOV EDX, IAppDom
.ELSE
        MOV EDX, IDefaultDomain
.ENDIF
        PUSH EDX   
        MOV EDX,[EDX]   
        CALL DWORD PTR [EDX+228]


What I'd like to know is how you determined the vtable order of the AppDomain object,...(or, is it the _AppDomain Interface ???) It's not in mscoree.h.

mabdelouahab

_AppDomain interface is in mscorlib.dll
Quote from: Zen on June 24, 2016, 05:03:03 AM
What I'd like to know is how you determined the vtable order of the AppDomain object,...(or, is it the _AppDomain Interface ???) It's not in mscoree.h.
the vtable order of the AppDomain object? There is no way to know this ( vtable order of the AppDomain object not equal vtable order of the _AppDomain interface)

Zen

That doesn't make sense.
How did you figure out what method was located at:
DWORD PTR [EDX+228] ???
The reason I'd like to know, is that I'm trying to verify your code in (DotNetHelper.inc), and when you have a line of code like,
CALL DWORD PTR [EDX+228]...
it looks like a COM interface method invocation. You do this at many places in your code, and if I have a reference to the interface virtual table, like the file, mscoree.h, then I can determine what it is you are calling with complete accuracy.
...So, I'm guessing that you used a .NET Framework disassembler, like ILSpy, or something,...:icon_eek:
...And, I'm also guessing that the call: DWORD PTR [EDX+228] ??? is something like: public Assembly[] GetAssemblies()

Here is the output of IL Spy for AppDomain (unfortunately, it doesn't show you the vtable order, or whatever structure the interface has):   

mabdelouahab

Quote from: Zen on June 24, 2016, 06:52:22 AM
That doesn't make sense.
How did you figure out what method was located at:
DWORD PTR [EDX+228] ???
is _AppDomain interface not AppDomain object  :biggrin: from mscorlib.tlb
I will explain to you when I have the time

Zen

#59
This is REALLY getting exciting !!!
Interface Definitions and Type Libraries, MSDN

...And, here (the zip file below), is the output from the OLE/COM Object Viewer for the mscorlib.tlb type library, version 4, for the _APPDomain interface (this is actually the 64-bit version):

And,...now,...I have my answer to the question (How did you figure out what method was located at: DWORD PTR [EDX+228] ??? ):
HRESULT _stdcall GetAssemblies([out, retval] SAFEARRAY(_Assembly*)* pRetVal);

DANG,...MABDELOUAHAB,...you must be a GENIUS !!! It would have taken me all eternity to figure all that out !!! And, on top of that, you had to translate all the documentation into arabic (so that you could understand it), write the code in English, post it to the MASM Forum, read all of our annoying comments in english, translate that back into arabic,...and, on and on and on,...:bgrin:
:dazzled: I'm AMAZED !!!  :dazzled: