flat assembler
Message board for the users of flat assembler.

Index > Windows > sIID_IShellExtInit from MASM to FASM

Author
Thread Post new topic Reply to topic
ManOfSteel



Joined: 02 Feb 2005
Posts: 1154
ManOfSteel 23 Jul 2007, 20:17
Hello,

does someone know how to translate this MASM code to FASM?

It comes from "\masm32\COM\include\shlobj.inc".

Code:
sIID_IShellExtInit  TEXTEQU <{0000214E8H, 00000H, 00000H,  \
                             {0C0H, 000H, 000H, 000H, 000H, 000H, 000H, 046H}}>

LPSHELLEXTINIT   typedef  DWORD
LPPSHELLEXTINIT  typedef  PTR LPSHELLEXTINIT

_vtIShellExtInit MACRO CastName:REQ
    ; IUnknown methods 
    _vtIUnknown CastName
    ; IShellExtInit methods
    &CastName&_Initialize  comethod4 ?
ENDM

IShellExtInit                      STRUCT
    _vtIShellExtInit IShellExtInit
IShellExtInit                      ENDS
    


Thank you in advance.
Post 23 Jul 2007, 20:17
View user's profile Send private message Reply with quote
ManOfSteel



Joined: 02 Feb 2005
Posts: 1154
ManOfSteel 25 Jul 2007, 06:50
Any idea?
Post 25 Jul 2007, 06:50
View user's profile Send private message Reply with quote
madmatt



Joined: 07 Oct 2003
Posts: 1045
Location: Michigan, USA
madmatt 25 Jul 2007, 08:44
Give this a try.

Code:
format PE GUI 4.0
entry start

include 'win32a.inc'

struct GUID
       Data1 dd ?
       Data2 dw ?
       Data3 dw ?
       Data4 db 8 dup(?)
ends

interface IShellExtInit,\
          QueryInterface,\
          AddRef,\
          Release,\
          Initialize

section '.data' data readable writeable
  MyShellExtInit IShellExtInit
  IID_IShellExtInit GUID $214E8, 0, 0, <$C0,0,0,0,0,0,0,$46>

section '.code' code readable executable
  invoke  CoInitialize, NULL
  invoke  CoCreateInstance, NULL, NULL, CLSCTX_INPROC_SERVER,  IID_IShellExtInit, MyShellExtInit
  cominvk MyShellExtInit, Initialize    
Post 25 Jul 2007, 08:44
View user's profile Send private message Reply with quote
ManOfSteel



Joined: 02 Feb 2005
Posts: 1154
ManOfSteel 26 Jul 2007, 10:06
I figured it all out yesterday. My final code was not far from yours. But thanks anyway.
By the way, I'm trying to program a shell extention and it's quite tough. You would not by chance know of anyone written in fasm?
Post 26 Jul 2007, 10:06
View user's profile Send private message Reply with quote
madmatt



Joined: 07 Oct 2003
Posts: 1045
Location: Michigan, USA
madmatt 27 Jul 2007, 07:50
No I don't, sorry.
Post 27 Jul 2007, 07:50
View user's profile Send private message Reply with quote
ManOfSteel



Joined: 02 Feb 2005
Posts: 1154
ManOfSteel 28 Jul 2007, 14:55
Hello,

I've been trying to make an "easier" COM server that only shows a simple message box when a client requests its object. But it's not working any better than my previous attempt.

For the last few days, I've been reading dozens MSDN pages and tutorials on COM, and checking C++ and MASM source code to no avail. I can't make it work.

Almost everytime I try to register the server (with 'regsvr32 /c'), I get the following exception. Sometimes the error doesn't show, but the server is not registered and the client - which works well with other servers of the same kind - returns an error code. What is constant is the system going awry after any registration attempt.

I've attached the code and would greatly appreciate any help.

Quote:

REGSVR32 caused an invalid page fault in
module KERNEL32.DLL at 016f:bff7a125.
Registers:
EAX=8175ae74 CS=016f EIP=bff7a125 EFLGS=00010212
EBX=82ff6918 SS=0177 ESP=0056df38 EBP=0056df78
ECX=8170203c DS=0177 ESI=8175ae74 FS=3ba7
EDX=00100000 ES=0177 EDI=0189baa4 GS=0000
Bytes at CS:EIP:
8b 03 a8 01 74 25 25 fc ff ff 0f 8b 53 08 03 f8
Stack dump:
0056df78 0189baa4 8175ad68 0000010c bff7a3a0 81702000 8175ae74 0189baa4 00000000 8170200c 81702000 8175ad68 00000000 00000000 00082ff6 0008175b


Description:
Download
Filename: msgbox.asm
Filesize: 11.5 KB
Downloaded: 301 Time(s)

Post 28 Jul 2007, 14:55
View user's profile Send private message Reply with quote
SFeLi



Joined: 03 Nov 2004
Posts: 138
SFeLi 29 Jul 2007, 06:31
In DllRegisterServer/DllUnregisterServer:
Code:
invoke  RegOpenKey,HKEY_CLASSES_ROOT,szCLSID,[hKey]    

Quote:
phkResult — Points to a variable that receives the handle of the opened or created key.

Code:
        lea     eax,[hKey]
        invoke  RegOpenKey,HKEY_CLASSES_ROOT,szCLSID,eax
    


In DllGetClassObject (and later):
Code:
        mov     eax,[eax]          ;Get POINTER to VTABLE from object.
        call    dword [eax + 0]    ;And call the first method (QueryInterface).
; and
        pICF                    IClassFactory ;<-- Invalid. Must be POINTER to INITIALIZED vtable.
        ICFRefCount             dd 1             
    

Also look at the include/macro/com32 — you're incorrectly using interface macro. Construct vtable manually or use structures.

PS: What extension do you want to write?
Post 29 Jul 2007, 06:31
View user's profile Send private message Reply with quote
ManOfSteel



Joined: 02 Feb 2005
Posts: 1154
ManOfSteel 29 Jul 2007, 18:15
Hello SFeLi and thanks for your reply.

Quote:

mov eax,[eax] ;Get POINTER to VTABLE from object.
call dword [eax + 0] ;And call the first method (QueryInterface).
; and
pICF IClassFactory ;<-- Invalid. Must be POINTER to INITIALIZED vtable.
ICFRefCount dd 1

I don't really understand. pICF is like a shortcut to the IClassFactory interface pointer whose methods (i.e. vtable) are all pointing to the implemented procedures (QueryInterface_CF, AddRef_CF, etc).


Quote:
Also look at the include/macro/com32 ? you're incorrectly using interface macro.

How should I use it? I've always used it that way in my COM clients (ShellLink, ActiveDesktop, DirectSound, etc) without any problem. Why should it be different with servers?


Quote:
Construct vtable manually or use structures.

Are you suggesting I use dword arrays like this:
Code:
IClassFactory:
dd ?
dd QueryInterface_CF
dd AddRef_CF
dd Release_CF
dd CreateInstance
dd LockServer

IMsgbox:
dd ?
dd QueryInterface_MC
dd AddRef_MC
dd Release_MC
dd DoMsgbox
    


or

Code:
struct IClassFactory
interface dd ?
QueryInterface_CF dd ?
AddRef_CF dd ?
Release_CF dd ?
CreateInstance dd ?
LockServer dd ?
ends

IMsgbox:
interface dd ?
QueryInterface_MC dd ?
AddRef_MC dd ?
Release_MC dd ?
DoMsgbox dd ?
ends
    


Correct me if I'm wrong, but isn't that what the interface macro actually does?


Quote:
PS: What extension do you want to write?

This code is not an extension. It only allows the client to use DoMsgbox to display a message box. I'm just trying to learn how COM servers work.
My previous (failed) attempt at COM servers was a context menu shell extension.
Post 29 Jul 2007, 18:15
View user's profile Send private message Reply with quote
SFeLi



Joined: 03 Nov 2004
Posts: 138
SFeLi 29 Jul 2007, 21:14
Quote:
interface macro. How should I use it? I've always used it that way in my COM clients. Why should it be different with servers?

The only thing that interface macro does is generate offsets for methods. For example:
Code:
interface IXyzzy,\
    QueryInterface,\
    AddRef,\
    Release,\
    Foo,\
    Bar,\
    Baz

;will generate virtual-at-0 equivalent of

label IXyzzy.QueryInterface dword at 0x00000000
label IXyzzy.AddRef         dword at 0x00000004
label IXyzzy.Release        dword at 0x00000008


If you want to define vtable, then:
Code:
;either define it manually:
IXyzzyVtbl dd IXyzzy_QueryInterface
           dd IXyzzy_AddRef
           dd IXyzzy_Release
           dd …         

;or create a structure for it:

struct IXyzzy
  QueryInterface dd ?
  AddRef         dd ?
  Release        dd ?
  …
ends

IXyzzyVtbl IXyzzy IXyzzy_QueryInterface,\
                  IXyzzy_AddRef,\
                  IXyzzy_Release
    



Quote:
pICF is like a shortcut to the IClassFactory interface pointer whose methods (i.e. vtable) are all pointing to the implemented procedures (QueryInterface_CF, AddRef_CF, etc).

See above. It points to NULL in your code:
Quote:
Output of “pICF IClassFactory” is: 0x004010b1: 0x00000004 bytes (00 00 00 00)


Quote:
Are you suggesting I use dword arrays

Yes. But (hint!) why not to have static vtables?

I attached my old source, that implements fake COM object, maybe you can find something useful there.


Description:
Download
Filename: fakecom.zip
Filesize: 3.22 KB
Downloaded: 304 Time(s)



Last edited by SFeLi on 30 Jul 2007, 17:39; edited 1 time in total
Post 29 Jul 2007, 21:14
View user's profile Send private message Reply with quote
ManOfSteel



Joined: 02 Feb 2005
Posts: 1154
ManOfSteel 30 Jul 2007, 13:41
Hello and thanks for the source code.

I went over my code and corrected all errors about interfaces and vtables. I defined the ClassFactory object as a static object.

When I try to register it, regsvr32 shows a successful registration message, but the server is still not registered properly.

I've attached the modified code.

Thanks for continuing to help me.


Description:
Download
Filename: msgbox2.asm
Filesize: 11.53 KB
Downloaded: 300 Time(s)

Post 30 Jul 2007, 13:41
View user's profile Send private message Reply with quote
SFeLi



Joined: 03 Nov 2004
Posts: 138
SFeLi 30 Jul 2007, 17:37
Quote:
the server is still not registered properly

Now you pass hKey correctly, but forgot about hKey2 and hKey3.

Code:
proc            CreateInstance pUnknownOuter,iid,ppv    

You forgot “this”.

And after fixing these errors… it works! Congratulations!

Not critical, but violates COM binary interface:
Code:
proc            DllGetClassObject pCLSID,pIID,ppv
        …
.else
        mov     [hr],CLASS_E_CLASSNOTAVAILABLE
.endif    

“ppv — indirect pointer to the requested interface or, if an error occurs, to NULL.” Same errors in CreateInstance (E_OUTOFMEMORY and CLASS_E_NOAGGREGATION cases).

Code:
       call    [IMsgbox.QueryInterface + eax]
       mov     [hr],eax
       .if     eax = 0  ; query failed, no valid pointer, release object
    

Failed? It returns HRESULT, not BOOL. And 0 is S_OK. Must be “.if eax < 0”.

And… Why do you release static class factory in DllGetClassObject? DllGetClassObject doesn't create ClassFactory object, nor increase its reference count, so it must not decrease it's reference count or call Release after calling QueryInterface.
Post 30 Jul 2007, 17:37
View user's profile Send private message Reply with quote
ManOfSteel



Joined: 02 Feb 2005
Posts: 1154
ManOfSteel 31 Jul 2007, 18:05
Hello SFeLi.

Yes, I had made some silly mistakes but it all works perfectly now.

I've also corrected the rest.

Now, I'll try my best with shell extensions.

Your help has been very useful. Thank you very much.
Post 31 Jul 2007, 18:05
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-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.