News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Implementation of the COM interface FileOpenDialog

Started by jorgon, February 19, 2025, 11:31:58 AM

Previous topic - Next topic

TimoVJL

#30
DELETED
May the source be with you

fearless


ognil

#32
Quotehttps://learn.microsoft.com/en-us/windows/win32/learnwin32/example--the-open-dialog-box
Nowhere in that example do I see any of those vtable members you put in your structures.
Where do those come from?

Maybe translation from C++ to MASM64 code without macros will help. :smiley: 

#include <windows.h>
#include <shobjidl.h>

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
    HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED |
        COINIT_DISABLE_OLE1DDE);
;*******************************************************************;
                        xor     ecx, ecx                            ; 2 = COINIT_APARTMENTTHREADED
                        mov     edx, 2 or 4                         ; 4 = COINIT_DISABLE_OLE1DDE ;Disables DDE for OLE1 support.
                        call    CoInitializeEx
;*******************************************************************;
    if (SUCCEEDED(hr))
    {
;*******************************************************************;
                        test    eax, eax
                        jne     Ret_1                               ; Exit with error
;*******************************************************************;
       
        IFileOpenDialog *pFileOpen;

        // Create the FileOpenDialog object.
        hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL,
                IID_IFileOpenDialog, reinterpret_cast<void**>(&pFileOpen));
;*******************************************************************;
                    lea        rax, pFileOpen                       ; Result: Interface CLSID_FileOpenDialog                    
                    lea        r9,  IID_IFileOpenDialog   
                    mov        [rsp+4*8], rax                       ; Interface CLSID_FileOpenDialog  
                    mov        r8d, CLSCTX_INPROC_SERVER            ; CLSCTX_INPROC_SERVER = 1
                    xor        edx, edx
                    lea        rcx, CLSID_FileOpenDialog
                    call       CoCreateInstance
;*******************************************************************;
 if (SUCCEEDED(hr))
        {
;*******************************************************************;
                    test    eax, eax
                    jne     Ret_1   
;*******************************************************************;

     // Show the Open dialog box.
     hr = pFileOpen->Show(NULL);
;*******************************************************************;

                    mov     rcx, pFileOpen                          ; rcx= Interface CLSID_FileOpenDialog  
                    xor     edx, edx                                ; parameter NULL for method  Show
                    mov     rax, [rcx]                              ; rax=addr of vTable
                    call    qword ptr [rax+3*8]                     ; call method  Show
; Methods (functions) from vTable of Interface CLSID_FileOpenDialog ; 
;        QueryInterface      dq  0*8                                ; *8 for 64 bit ; *4 for 32 bit
;        AddRef              dq  1*8
;        Release             dq  2*8
;        Show                dq  3*8    
;        SetFileTypes        dq  4*8 
;         .......
;        GetResult           dq  27*8
;
;*******************************************************************;

   // Get the file name from the dialog box.
     if (SUCCEEDED(hr))
        {
;*******************************************************************;
                    test    eax, eax
                    jne     Ret_1   
;*******************************************************************;

           IShellItem *pItem;
           hr = pFileOpen->GetResult(&pItem);
;*******************************************************************;
                    mov     rcx, pFileOpen                          ; rcx= Interface CLSID_FileOpenDialog  
                    lea     edx, pItem                              ; parameter pItem for method  GetResult
                    mov     rax, [rcx]                              ; rax=addr of vTable
                    call    qword ptr [rax+27*8]                    ; call method  GetResult
;*******************************************************************;
           if (SUCCEEDED(hr))
              {
;*******************************************************************;
                    test    eax, eax
                    jne     Ret_1   
;*******************************************************************;
    PWSTR pszFilePath;
     hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);
;*******************************************************************;
                    mov     rcx, pItem                              ; IShellItem interface
                    lea     r8,  pszFilePath                        ; 2nd parameter of method(function)  GetDisplayName
                    mov     edx, 80058000h                          ; 1st parameter - 80058000h=SIGDN_FILESYSPATH
                                                                    ; SIGDN_FILESYSPATH - Returns the item's file system path, if it has one
                    mov     rax, [rcx]                              ; vTable of interface IShellItem
                    call    qword ptr [rax+5*8]                     ; call method  GetDisplayName vTable of interface IShellItem
  ; 1st Part of IShellItemVtbl      
  ; QueryInterface   dq 0*8    
  ; AddRef           dq 1*8   
  ; Release          dq 2*8 
  ; BindToHandler    dq 3*8
  ; GetParent        dq 4*8
  ; GetDisplayName   dq 5*8
  ; ......
  ; Note: Search MS explanation for IShellItem::GetDisplayName  for details about all
  ; parameters of method(function)  GetDisplayName (SIGDN_FILESYSPATH,addr pszFilePath)
;*******************************************************************;
          // Display the file name to the user.
              if (SUCCEEDED(hr))
                {
;*******************************************************************;
                    test    eax, eax
                    jne     Ret_1   
;*******************************************************************;
                MessageBoxW(NULL, pszFilePath, L"File Path", MB_OK);
;*******************************************************************;
                    mov     r9d, MB_OK   
                    lea     r8,  pszUFilePath
                    lea     rdx, pszFilePath
                    xor     ecx, ecx
                    call    MessageBoxW
;*******************************************************************;
 CoTaskMemFree(pszFilePath);
                    }
;*******************************************************************;
                    lea    rcx, pszFilePath
                    call   CoTaskMemFree
;*******************************************************************;
                    pItem->Release();
                }
;*******************************************************************;
                    mov     rcx, pItem
                    mov     rax, [rcx]
                    call    qword ptr [rax+2*8]                     ; call method  Release from vTable of interface IShellItem
;*******************************************************************;
           }
            pFileOpen->Release();
        }
;*******************************************************************;
                    mov     rcx, pFileOpen
                    mov     rax, [rcx]
                    call    qword ptr [rax+2*8]                     ; call method  Release from vTable of interface IShellItem
;*******************************************************************;
        CoUninitialize();
    }
    return 0;
}
;*******************************************************************;
                    call    CoUninitialize
                    xor     eax, eax
                    ret
;*******************************************************************;

Result-> MASM64 code without macros :biggrin: 


.data?
pFileOpen   dq ?
pItem       dq ?
pszFilePath dq ?

.data
pszUFilePath dw "F","i","l","e"," ","P","a","t","h",0,0

CLSID_FileOpenDialog dd 0DC1C5A9Ch
dw 0e88ah,4ddeh,a5a1h
db 60,0F8h,02ah,20h,0aeh,0f7h

IID_IFileOpenDialog  dd d57c7288h
dw 0d4adh,4768h,0be02h
db 9dh,96h,95h,32h,0d9h,060h

.code
;*******************************************************************;
                    xor     ecx, ecx                                ; 2 = COINIT_APARTMENTTHREADED
                    mov     edx, 2 or 4                             ; 4 = COINIT_DISABLE_OLE1DDE ;Disables DDE  for OLE1 support.
                    call    CoInitializeEx

                    test    eax, eax
                    jne     Ret_1                                   ; Exit with error
                   
                    lea     rax, pFileOpen                          ; Result: Interface CLSID_FileOpenDialog                    
                    lea     r9,  IID_IFileOpenDialog   
                    mov     [rsp+4*8], rax                          ; Interface CLSID_FileOpenDialog  
                    mov     r8d, CLSCTX_INPROC_SERVER               ; CLSCTX_INPROC_SERVER = 1
                    xor     edx, edx
                    lea     rcx, CLSID_FileOpenDialog
                    call    CoCreateInstance

                    test    eax, eax
                    jne     Ret_1   

                    mov     rcx, pFileOpen                          ; rcx= Interface CLSID_FileOpenDialog  
                    xor     edx, edx                                ; parameter NULL for method  Show
                    mov     rax, [rcx]                              ; rax=addr of vTable
                    call    qword ptr [rax+3*8]                     ; call method  Show

                    test    eax, eax
                    jne     Ret_1   

                    mov     rcx, pFileOpen                          ; rcx= Interface CLSID_FileOpenDialog  
                    lea     edx, pItem                              ; parameter pItem for method  GetResult
                    mov     rax, [rcx]                              ; rax=addr of vTable
                    call    qword ptr [rax+27*8]                    ; call method  GetResult

                    test    eax, eax
                    jne     Ret_1   

                    mov     rcx, pItem                              ; IShellItem interface
                    lea     r8,  pszFilePath                        ; 2nd parameter of method(function)  GetDisplayName
                    mov     edx, 80058000h                          ; 1st parameter - 80058000h=SIGDN_FILESYSPATH
                                                                    ; SIGDN_FILESYSPATH - Returns the item's file system path, if it has one
                    mov     rax, [rcx]                              ; vTable of interface IShellItem
                    call    qword ptr [rax+5*8]                     ; call method  GetDisplayName vTable of interface IShellItem

                    test    eax, eax
                    jne     Ret_1   

                    mov     r9d, MB_OK   
                    lea     r8,  pszUFilePath
                    lea     rdx, pszFilePath
                    xor     ecx, ecx
                    call    MessageBoxW
                    lea     rcx, pszFilePath
                    call    CoTaskMemFree

                    mov     rcx, pItem
                    mov     rax, [rcx]
                    call    qword ptr [rax+2*8]                     ; call method  Release from vTable of interface IShellItem

                    mov     rcx, pFileOpen
                    mov     rax, [rcx]
                    call    qword ptr [rax+2*8]                     ; call method  Release from vTable of interface FileOpenDialog
                             
                    call    CoUninitialize
                    xor     eax, eax
                    ret
Ret_1:
                    mov     eax, 1   
                    ret
"Not keeping emotions under control is another type of mental distortion."

TimoVJL

#33
DELETED
May the source be with you

NoCforMe

Quote from: jorgon on February 20, 2025, 08:30:45 PM
Quote from: NoCforMe on February 20, 2025, 07:22:52 PMWell, that's nice, but you didn't answer the question. So sorry, no award for you yet.

I still have no clue how to determine which version of a file (say, ShObjIdl_core.h) is the correct one. Or, let's say, a version that will at least work for converting to an .inc file. (And yes, I can do that by hand.)

In order to win my award, I answer as follows.

You can't tell which is the correct one, apart from looking inside to see if it has what you are looking for, but it matters a lot less than you would think because the names of the functions, the number of parameters the function expects, and the types of those parameters will never change.  If they did, progs compiled using the old headers would fail.

What??? Our course it matters, a lot.
Are you purposely being obtuse here? Because that first GitHub version of ShObjIdl_core.h that I linked to above did not even have the elements required to construct the IFileOpenDialog vtable.
I would say that totally matters.

I somehow get the feeling you're not really paying attention to my questions, because all I seem to get out of you is a lot of handwaving and vague answers. Might be my misperception, of course, but still ...

So is the only way to see whether a header file is suitable to open it and look for the specific structure members (and possibly other items, like #defines) you need? And how would you even know which ones to look for? What names do you use? Are they listed in the Micro$oft Learn documentation for the functions you'll be using?
Assembly language programming should be fun. That's why I do it.

ognil

QuoteI somehow get the feeling you're not really paying attention to my questions, because all I seem to get out of you is a lot of handwaving and vague answers.

Ask QWEN CHAT and/or Deep-Seek. :badgrin:  :skrewy:
"Not keeping emotions under control is another type of mental distortion."

NoCforMe

Quote from: ognil on February 21, 2025, 11:43:11 AM
QuoteI somehow get the feeling you're not really paying attention to my questions, because all I seem to get out of you is a lot of handwaving and vague answers.

Ask QWEN CHAT and/or Deep-Seek. :badgrin:  :skrewy:

No.
Assembly language programming should be fun. That's why I do it.

NoCforMe

Quote from: TimoVJL on February 21, 2025, 09:21:39 AMCOM Dual Interface
Some COM object interfaces are for languages like VB and script languages, and those might use GetIDsOfNames() and Invoke() for methods, and can have a limited vTable


Timo--your tangential reply is not helpful at all.
Assembly language programming should be fun. That's why I do it.

TimoVJL

#38
DELETED
May the source be with you

NoCforMe

OK, Timo, I get it that those files can be found all over the place online.
Still doesn't answer my questions as to how to 1) find them and 2) confirm that they're suitable for your application.
Assembly language programming should be fun. That's why I do it.

sinsi

Quote from: NoCforMe on February 21, 2025, 12:57:42 PMOK, Timo, I get it that those files can be found all over the place online.
Still doesn't answer my questions as to how to 1) find them and 2) confirm that they're suitable for your application.
1) Download the SDK
2) Convert the .H to a .INC and it's suitable

The Microsoft Learn page usually has which header file the interface is defined in.
One gotcha about the Learn page is that the methods are usually in alphabetical order, not vtable order :rolleyes:.

NoCforMe

Quote from: sinsi on February 21, 2025, 01:39:05 PMOne gotcha about the Learn page is that the methods are usually in alphabetical order, not vtable order :rolleyes:.

Are they in the correct order in the header files? (I would guess by definition yes, but that's just a guess.)

Alphabetical order would make sense for C++ programmers, who don't have build a vtable: that's already done for them.
Assembly language programming should be fun. That's why I do it.

sinsi

They should be in order, since that is the definition.
One thing to look for in the C++ definition is whether it inherits another interface
IShellLinkW : public IUnknownMost interfaces that I've seen inherit IUnknown, and that's the first few entries in the vtable.

It might be worthwhile looking at interfaces from the other side, there was an article in Stack Overflow (maybe Code Project) where someone went through building a simple interface in C.

sinsi

Hey mods, this has grown beyond GoAsm ,maybe split it?

Villuy

Quote from: jorgon on February 19, 2025, 11:31:58 AMIt turns out this is easier to code in assembler than in "C" because everything is obvious and there are no compiler quirks to be circumvented.

I don't understand what you mean:

1) Assembly + WinAPI is easier than C + WinAPI

or

2) GoAsm not needs WinAPI at all.