News:

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

Main Menu

COM Interface Pointer Question

Started by Zen, August 02, 2015, 07:36:42 AM

Previous topic - Next topic

Zen

OK,...I have a question concerning the values of COM Class and Interface pointers.
I'm still working on a COM application that is driving me crazy,...but, I'm making progress.
I have several components,...and, they all seem to work adequately. The current component that I'm testing instantiates a COM Class, using the CLSID from the registry. The method I'm using calls CreateClassMoniker,...and, then,...IMoniker.BindToObject to return a pointer to a the IUnknown interface of the COM Class. This works OK. As mentioned in a previous post (COM Question -- Class Moniker), I have prototyped the various COM interfaces as MASM compatible structures, and all that works OK. 

There is one thing that mystifies me at this point:

  • A number of the 32-bit COM DLLs return pointer values that are not addresses within the loaded COM DLL. I call LoadLibrary after I instantiate a COM Class (I have the string for the location path of the DLL from a registry search), and I use the HMODULE return to get the Base Address of the loaded module. Then I call GetModuleInformation to get the size of the loaded module. Pretty simple stuff.
What I'd like to do is determine which module has the implementations of the various COM methods that the returned COM Class (IUnknown) pointers point to. I assume that there is a dependancy to the loaded COM DLL that contains the IUnknown method implementations.  :dazzled:

When I Google the problem, the only possibility that I found is to use the Process Environment Block (PEB) structure to retrieve a list of modules currently loaded in the process's address space,...as described in the following blog:
Retrieving Kernel32's Base Address, Harmony Security
Zen

dedndave

the COM interface pointer is a pointer to data
that data is a list of pointers to the different functions

try this
    mov     edx,pInterface
    mov     eax,[edx+16]
    print   uhex$(eax),13,10


i used "+16" to skip over the IUnknown pointers
although, that may not be necessary

Zen

Hi, DAVE,
Yeah, I'm doing something very similar in my code. I then print out the values to a text file as a check on accuracy. Most of the time it works as exected,...the pointer values are addresses within the loaded COM Dll. But, occasionally, these addresses are beyond the address limit of the loaded COM DLL. And, the pointers are valid,...I can do something like this:
      mov esi, IUnknownPtr
      mov esi, [esi]
      ASSUME esi:PTR IUnknown
      invoke [esi].IUnknown.AddRef, IUnknownPtr
      ASSUME esi:nothing    ;   

...And,...
      mov esi, IUnknownPtr
      mov esi, [esi] ;    pointer IUnknown VTable   
      invoke [esi].IUnknown.Release, IUnknownPtr

...In all the cases I've tested, it works...and, the application doesn't crash,...

I found this information in Windows Internals:
QuoteLoaded Module Database
The loader maintains a list of all modules (DLLs as well as the primary executable) that have been loaded by a process. This information is stored in a per-process structure called the process environment block, or PEB, namely, in a substructure identified by Ldr and called PEB_LDR_DATA. In the structure, the loader maintains three doublylinked lists, all containing the same information but ordered differently (either by load order, memory location, or initialization order). These lists contain structures called loader data table entries (LDR_DATA_TABLE_ENTRY) that store information about each module.
Zen

dedndave

i suspect windows is free to move loaded modules around, in order to best use available memory

TouEnMasm

Quote
What I'd like to do is determine which module has the implementations of the various COM methods that the returned COM Class
The Pointers on the COM method are put in an array in a special memory shared by the dll and the executable.
It is the system who do that at start looking in the registry to know which module to load.

It is in The registry you have to search the answer.Search the registry keys with the CLSID or the IID of the interface and you got
the path of the loaded module (dll).

Quote
{0000000f-0000-0000-C000-000000000046}   IMoniker
Fa is a musical note to play with CL

TouEnMasm

Quote
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\CLSID\{0000031A-0000-0000-C000-000000000046}]
@="ClassMoniker"

[HKEY_CLASSES_ROOT\CLSID\{0000031A-0000-0000-C000-000000000046}\InprocServer32]
@="combase.dll"

[HKEY_CLASSES_ROOT\CLSID\{0000031A-0000-0000-C000-000000000046}\ProgID]
@="clsid"

Fa is a musical note to play with CL

mabdelouahab

Quote from: dedndave on August 02, 2015, 08:45:26 AM
the COM interface pointer is a pointer to data
that data is a list of pointers to the different functions
Right, the COM interface pointer is a pointer to data allocated (Usually) by CoTaskMemAlloc that uses COM's IMalloc allocator that use the default per-process heap


Zen

Thanks DAVE, TOUTENMASM, and MABDELOUAHAB for the responses.
I shall investigate further,...:dazzled:

...But, just to clarify,...
I have printed out the address value of the COM Class IUnknown pointer (and, it definitely is NOT located in the loaded COM Server DLL.) In all the cases I've tested, this address is always a very low number (relatively speaking),...
...So, no doubt TOUTENMASM is correct about this:
Quote from: TOUTENMASMThe Pointers on the COM method are put in an array in a special memory shared by the dll and the executable.It is the system who do that at start,...

...As I said in my first post:
Quote from: THE EVER-ANNOYING ZENWhat I'd like to do is determine which module has the implementations of the various COM methods,...
...Meaning,...the address of QueryInterface, AddRef, and Release,...for the COM Class, selected,...

Quote from: The COM Specification, 1995In reality, a pointer to an interface is actually a pointer to a pointer to the table of function pointers.

...I could post the actual code that I am using,...but, it's pretty simple, really,...I just de-reference the pointer to the COM Class VTable (that I got by de-referencing the original COM interface pointer returned from IMoniker.BindToObject),...and, that value is an address to the implementation of the first method in the COM VTable, QueryInterface (or,...at least,...that is my thinking). Then, the addresses of the next two COM methods, AddRef and Release, are located in the next two DWORDs following the address for the QueryInterface implementation,...
Zen

shaikkareem

i would recommend use of OLE-COM Object Viewer which is a tool obtained on installing one of visual studio engines. In my work with COM this helped me a quite well.

TouEnMasm


To zen,
Your mind is unclear or there is a problem of vocabulary.
The module is given by the registry,already given
Quote
[HKEY_CLASSES_ROOT\CLSID\{0000031A-0000-0000-C000-000000000046}\InprocServer32]
@="combase.dll" <--------------------------- here a module (dll,exe ............)
There is no other value for module as you seems to say
citation
Quote
...Meaning,...the address of QueryInterface, AddRef, and Release,...for the COM Class, selected,...
To be more clear on the subject,have a look on the browser source code,he implement a lot of interface.
http://masm32.com/board/index.php?topic=3567.msg37504#msg37504

The com pointer give you the adress of the vector table
Having it,you have all the adress you want to know

Quote
   STIMoniker   STRUCT
      QueryInterface      FIMoniker_QueryInterface  ?
      AddRef                          comethod1 ?
      Release                         comethod1 ?
      GetClassID      FIMoniker_GetClassID  ?
      IsDirty                         comethod1 ?
      Load      FIMoniker_Load  ?
      Save      FIMoniker_Save  ?
      GetSizeMax      FIMoniker_GetSizeMax  ?
      BindToObject      FIMoniker_BindToObject  ?
      BindToStorage      FIMoniker_BindToStorage  ?
      Reduce      FIMoniker_Reduce  ?
      ComposeWith      FIMoniker_ComposeWith  ?
      Enum      FIMoniker_Enum  ?
      IsEqual      FIMoniker_IsEqual  ?
      Hash      FIMoniker_Hash  ?
      IsRunning      FIMoniker_IsRunning  ?
      GetTimeOfLastChange      FIMoniker_GetTimeOfLastChange  ?
      Inverse      FIMoniker_Inverse  ?
      CommonPrefixWith      FIMoniker_CommonPrefixWith  ?
      RelativePathTo      FIMoniker_RelativePathTo  ?
      GetDisplayName      FIMoniker_GetDisplayName  ?
      ParseDisplayName      FIMoniker_ParseDisplayName  ?
      IsSystemMoniker      FIMoniker_IsSystemMoniker  ?
   STIMoniker   ENDS


When you have the com pointer:
Quote
      mov edx,compointer
      mov eax,[edx] ;you get the QueryInterface adress in the specified module
      add edx,4 ;in 32 bit
      mov eax,[edx] ;you get AddRef  adress in the specified module
      ------ and so on,last is IsSystemMoniker
     



Fa is a musical note to play with CL