flat assembler
Message board for the users of flat assembler.

Index > Windows > Interface pointer

Author
Thread Post new topic Reply to topic
AE



Joined: 07 Apr 2022
Posts: 59
AE 01 Jan 2023, 13:40
Can't get a pointer to an IFileSystemBindData interface.
Maybe someone has encountered something like this?

IUnknown or Desktop ->QueryInterface both return E_NOINTERFACE for both IID_IFileSystemBindData and IID_IFileSystemBindData2


What for

Another CPP example


Happy New Year, by the way! Smile
Post 01 Jan 2023, 13:40
View user's profile Send private message Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 2016
Furs 01 Jan 2023, 19:42
From the description of what you linked, sounds like you are supposed to implement that interface, and then pass it to ParseDisplayName, which will call back into your implemented interface for optimizations. You need to make a custom object exposing that interface for some reason.

I've used shell APIs and ParseDisplayName, but never this IFileSystemBindData thing so I can't help with details unfortunately.

And Happy New Year to you too. Wink
Post 01 Jan 2023, 19:42
View user's profile Send private message Reply with quote
AE



Joined: 07 Apr 2022
Posts: 59
AE 01 Jan 2023, 19:54
Furs wrote:
you are supposed to implement that interface


Recreating the structure of an interface is not a problem, but how to fill it with pointers to methods of this interface?
That's the main problem.

It looks like you need a pointer to some private interface from which you can successfully call QueryInterface for IFileSystemBindData...
Post 01 Jan 2023, 19:54
View user's profile Send private message Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 2016
Furs 02 Jan 2023, 18:41
Sorry, I don't understand what you mean. Are you asking how COM interfaces work?

Basically, an "interface" is just a struct with a pointer to a vtbl that has those methods. If you don't have the Windows SDK you can look at MinGW headers, or Wine, to see the order of the methods. They go in order.

For example this is the .idl file for the IFileSystemBindData interface:
Code:
/*****************************************************************************
 * IFileSystemBindData interface
 */
[
    object,
    uuid(01e18d10-4d8b-11d2-855d-006008059367),
    pointer_default(unique),
    local
]
interface IFileSystemBindData : IUnknown
{
    HRESULT SetFindData(
                [in] const WIN32_FIND_DATAW *pfd);
    HRESULT GetFindData(
                [out] WIN32_FIND_DATAW *pfd);
}    
So it has IUnknown methods first, then IFileSystemBindData, so it's like this:

Code:
struct IFileSystemBindData
{
  IFileSystemBindDataVtbl* lpVtbl;
};

struct IFileSystemBindDataVtbl
{
  IUnknown_QueryInterface function pointer;
  IUnknown_AddRef function pointer;
  IUnknown_Release function pointer;
  SetFindData function pointer;
  GetFindData function pointer;
};    
So you have to implement that vtbl, put it somewhere in your object, and pass that to the Windows shell API. Let's say your object layout is like this:
Code:
struct obj
{
  member1;
  member2;
  member3;
  member4;
};    
You can place the interface vtbl anywhere:
Code:
struct obj
{
  member1;
  member2;
  member3;
  IFileSystemBindData here;
  member4;
};    
Then you store your own vtbl's address into "here.lpVtbl" (which is usually in read-only memory since it doesn't change). Your vtbl will contain function pointers to your own methods.

To obtain the pointer to your "struct obj" from within an interface's method, just do some byte subtraction, i.e.:
Code:
; assume the "This" pointer is in rcx
lea rax, [rcx - offset_to_here_in_struct]
; rax is now pointer to the object

; e.g. if member1, member2, and member3 are all pointers, then offset_to_here_in_struct is 3 * 8 = 24    
Remember when the windows API wants the interface, you pass it the address of "here" above. It doesn't know the object's struct, nor does it need to. All it knows is that there's a vtbl at the pointer passed that implements the interface. That's the point of interfaces.

You could pass a different object, with completely different layout and different vtbl, and the Windows API would work with it with no changes. It's "abstract". It's same as virtual functions in C++. (in fact that's how it is implemented in C++)


Implementing multiple interfaces on the same object is the same, just put more vtbls, and then QueryInterface return address of each interface when asked. But since IFileSystemBindData inherits from IUnknown, you don't have to implement IUnknown as a separate vtbl: just return the same address as IFileSystemBindData in its QueryInterface. It will "just work".
Post 02 Jan 2023, 18:41
View user's profile Send private message Reply with quote
AE



Joined: 07 Apr 2022
Posts: 59
AE 03 Jan 2023, 09:19
Thank you! That clarified a lot.
Post 03 Jan 2023, 09:19
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2023, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.