flat assembler
Message board for the users of flat assembler.

Index > Windows > How to implement virtual function table in a DLL

Author
Thread Post new topic Reply to topic
mns



Joined: 20 Dec 2007
Posts: 150
Location: Piliyandala,Sri lanka
mns 11 Apr 2023, 17:32
I am trying to understand how Vtable is created in a DLL
I have made the following example code so far,
Code:
format PE GUI 4.0  DLL
entry startDLL


 include 'WIN32A.inc'
 ;include 'rcWin32p16.inc'
    struct   MYINTERFACE
             QueryInterface             dd ?
             AddRef                     dd ?
             Release                    dd ?
             GetMsgBox                  dd ?
             GetErrorMsgBox             dd ?
    ends

;/////////////////////////////////////////////////////////////////////////////////////////////////////
 section '.data' data readable writeable
;========================================================================================================
 myMSGBOXHead    db 'Error MSGBOX Heading',0
 myError         db 'This is a error',0
 mytext          db 'This is a test text',0

 myInterface     MYINTERFACE



;======================================================================================================
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;/////////////////////////////////////////////////////////////////////////////////////////////////////
 section '.code' code readable executable
;======================================================================================================
;----------------------------------Entry point--------------------------------------------------------
   proc         startDLL  hInstance,Reason,Reserved

        mov          eax,TRUE
        ret

   endp
;----------------------------------------------------------------------------------------------------------
   proc         myInterfaceFunc

        call      mydecoderVTBL
        mov       eax,mydecoderVTBL
        ret

   endp


;----------------------------------------------------------------------------------------------------------

;----------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------
   mydecoderVTBL:
        mov          dword[myInterface],myInterface_QueryInterface
        mov          dword[myInterface+4],myInterface_AddRef
        mov          dword[myInterface+8],myInterface_Release
        mov          dword[myInterface+12],myInterface_GetMsgBox
        mov          dword[myInterface+16],myInterface_GetErrorMsgBox
        ret
;----------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------

   myInterface_QueryInterface:
   ;code here
        ret
;----------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------

   myInterface_AddRef:
        ;code here
        ret
;----------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------

   myInterface_Release:
       ;code here
         ret
;----------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------

   myInterface_GetErrorMsgBox:
        lea             eax,[myError]
        lea             edx,[myMSGBOXHead]
        invoke          MessageBox, 0,eax,edx, MB_OK

        ret
;----------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------

   myInterface_GetMsgBox:
        lea             eax,[mytext]
        lea             edx,[myMSGBOXHead]
        invoke          MessageBox, 0,eax,edx, MB_OK

        ret
;----------------------------------------------------------------------------------------------------------











;==========================================================================================================
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;/////////////////////////////////////////////////////////////////////////////////////////////////////
 section '.idata' import data readable
;=======================================================================================================
 library    kernel32,'kernel32.dll',\
            user32,'USER32.DLL'

 include 'api/kernel32.inc'
 include 'api/USER32.inc'

;=======================================================================================================
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;/////////////////////////////////////////////////////////////////////////////////////////////////////
 section '.edata' export data readable
;=======================================================================================================

    export 'dlltest2.dll',\
            myInterfaceFunc,'myInterfaceFunc'

;=======================================================================================================
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;/////////////////////////////////////////////////////////////////////////////////////////////////////
section '.reloc' fixups data readable discardable
;=======================================================================================================
  if $=$$
    dd 0,8              ; if there are no fixups, generate dummy entry
  end if
;=======================================================================================================
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
    

Several things I cannot understand,
1). How vtable is created when loading the DLL (Is my way in the code correct ?)
2). What address in this code(if this has specified CLSID) CoCreateInstance function will return and How it does that

Please could someone help ? Sad Embarassed


Description:
Download
Filename: dlltest2.ASM
Filesize: 5.94 KB
Downloaded: 252 Time(s)



Last edited by mns on 12 Apr 2023, 07:29; edited 1 time in total
Post 11 Apr 2023, 17:32
View user's profile Send private message Send e-mail Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 804
Location: Russian Federation, Sochi
ProMiNick 11 Apr 2023, 19:28
If thou want Vtable would be accesssible as COM object - DLL should export DllGetClassObject where returned interface IClassFactory, after that called ClassFactory@CreateInstance method that craeted final Interface.
IClassFactory is already defined interface like (i mean definition itself not method content)
Code:
myInterface     MYINTERFACE myInterface_QueryInterface,myInterface_AddRef,myInterface_Release,myInterface_GetMsgBox,myInterface_GetErrorMsgBox    

if thour target is not COM object so QueryInterface,AddRef & Release are rudiment in custom implementation of Vtable they not needed at all.

If thou realy interest in COM technology in assembly implementation request in any internet indexers "fasmpack" than look in folder "\DEMOS\EXECS\WINDOWS\WIN32\COM_TECH\SERVERS\SHELLEX\" inside of it.
Post 11 Apr 2023, 19:28
View user's profile Send private message Send e-mail Reply with quote
mns



Joined: 20 Dec 2007
Posts: 150
Location: Piliyandala,Sri lanka
mns 12 Apr 2023, 09:01
Thank you ProMiNick for the kind answer. But still I am not clear. You mean,
To implement DllGetClassObject function(and export it), Where, DllGetClassObject function is,
Code:
proc         DllGetClassObject rclsid,riid,ppv
       ;newIClassFactory IClassFactory
        ;check rclsid = my class rclsid
        ;if yes,
        cominvk  newIClassFactory,CreateInstance,[riid],[ppv]
        ret
   endp
    


Is this correct? (now I am more confused Confused )
Post 12 Apr 2023, 09:01
View user's profile Send private message Send e-mail Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 804
Location: Russian Federation, Sochi
ProMiNick 12 Apr 2023, 11:58
Is this correct? - no.
COM technology request IClassFactory via exported from DLL function DllGetClassObject.
than outside of library (and internaly in libraries that realise COM from OS side) executed method CreateInstance of IClassFactory requested previously.
that method is able to build thour custom interface.

But without COM technology thou could import whatever thou want no matter function, or string, or some structure or interface.
And in that not COM interface thou don`t needed in QueryInterface,AddRef & Release. Just export address of interface and use it in executable that know that.
Post 12 Apr 2023, 11:58
View user's profile Send private message Send e-mail Reply with quote
mns



Joined: 20 Dec 2007
Posts: 150
Location: Piliyandala,Sri lanka
mns 13 Apr 2023, 04:12
I am trying to learn how vtable is created in loading a DLL. So far I get, DllGetClassObject function is the key for that. Could you please tell me (in simple terms) what should I do in DllGetClassObject function for that? (may be step wise).
Post 13 Apr 2023, 04:12
View user's profile Send private message Send e-mail Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 804
Location: Russian Federation, Sochi
ProMiNick 13 Apr 2023, 05:45
Code:
DllGetClassObject: procedure(rclsid,riid,ppv) ; returned requested ClassFactory!!! not COMobject itself
        push    ebx
        mov     ebx, [ppv]
        test    ebx, ebx
        jz      .ret_E_POINTER
        xor     eax, eax
        mov     [ebx], eax

        precmpGUID                            ; search ClassFactory corresponded to rclsid
        cld
        cmpGUID [rclsid],lpCLSID_QuickRegister
        postcmpGUID

        jnz     .ret_CLASS_E_CLASSNOTAVAILABLE
        comcall QRClassFactory_COMobject,IUnknown,QueryInterface,[riid],ebx
        jmp     .locret
      .ret_E_POINTER:
        mov     eax, E_POINTER
        jmp     .locret
      .ret_CLASS_E_CLASSNOTAVAILABLE:
        mov     eax, CLASS_E_CLASSNOTAVAILABLE
      .locret:
        pop     ebx
        ret
endp     


Every COM object has its own CLSID, in thour DLL could be one IClassFactory for every COM object or one IClassFactory for whole DLL.
DllGetClassObject firstly starts from checking args that ppv is valid pointer.
Than goes comparisons of requested rclsid with CLSIDS of COM objects described in DLL, and selected IClassFactory(selected COM object that realize IClassFactory interface, not IClassFactory interface) according to that comparison or returned CLASS_E_CLASSNOTAVAILABLE if CLSID not implemented in DLL. If detected COM object realized IClassFactory interface matched to requested CLSID, than executed its method QueryInterface.
That method mostly increase DLL_used counter.
Code:
DllCanUnloadNow: procedure()
        xor     eax,eax
        cmp     eax,[ServerLockCount]
        jz      .locret
        inc     eax
      .locret:
        ret
endp    

For checking if DLL could be unloaded is another export
that checks DLL_used counter (ServerLockCount) and if it is zero say yes - DLL could be unloaded, otherwise it says no.
By the way all QueryInterface of other COM objects realized in DLL increase that counter, they do that increase via subcall of another interface method AddRef, but before that each QueryInterface checks matching of requested IID to ones that interface accept.
for example COM object that realize IClassFactory interface accept IID only as IID_IClassFactory or as IID_IUnknown
Code:
QRClassFactory@QueryInterface: procedure(Self,riid,ppvObject)
        push    ebx
        mov     ebx, [ppvObject]
        test    ebx, ebx
        jz      .ret_E_POINTER
        xor     eax, eax
        mov     [ebx], eax

        precmpGUID
        cld
        cmpGUID [riid],lpIID_IUnknown
        je      .cmp_done
        cmpGUID [riid],lpIID_IClassFactory
      .cmp_done:
        postcmpGUID

        jnz     .ret_E_NOINTERFACE
        mov     eax, [Self]
        mov     [ebx], eax
        comcall eax, IClassFactory, AddRef
        xor     eax, eax
        jmp     .locret
      .ret_E_POINTER:
        mov     eax, E_POINTER
        jmp     .locret
      .ret_E_NOINTERFACE:
        mov     eax, E_NOINTERFACE
      .locret:
        pop     ebx
        ret
endp    
Post 13 Apr 2023, 05:45
View user's profile Send private message Send e-mail Reply with quote
mns



Joined: 20 Dec 2007
Posts: 150
Location: Piliyandala,Sri lanka
mns 13 Apr 2023, 06:55
Thank you very much ProMiNick
So to call "comcall QRClassFactory_COMobject,IUnknown,QueryInterface,[riid],ebx" in DllGetClassObject,
do we have to create QRClassFactory_COMobject(I mean the object it self to call QueryInterface) ? may be in the out side DllGetClassObject function?\
Post 13 Apr 2023, 06:55
View user's profile Send private message Send e-mail Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 804
Location: Russian Federation, Sochi
ProMiNick 13 Apr 2023, 07:32
Yes, object realised IClassFactory interface must be created in design time.
that one is example of object created in design time
Code:
myClassFactory     dd myClassFactory_QueryInterface,myClassFactory_AddRef,myClassFactory_Release,myClassFactory_CreateInstance    

that is simplest structure of object, but it could be
Code:
myClassFactory dd ...,myClassFactory_vtbl,...
myClassFactory_vtbl dd myClassFactory_QueryInterface,myClassFactory_AddRef,myClassFactory_Release,myClassFactory_CreateInstance    
or could be
Code:
myClassFactory dd ...,myClassFactory_Intf_Tbl,...
myClassFactory_Intf_Tbl dd ...,myClassFactory_Intf1_vtbl,...
myClassFactory_Intf1_vtbl dd myClassFactory_QueryInterface,myClassFactory_AddRef,myClassFactory_Release,myClassFactory_CreateInstance    

complexity of COM object and its structure could be any kind thou want, but with the only one requirement to COM object structure: any its method should be able to walk via current object structure and find other methods (implementation of every method should know current COM object structure)
Because assembler have no ability to hide methods or fields - that requirement is always passed in assembly, moreover in assembly it accesible even with static addresses in contrary to requirement of series of indirect accesses via object fields for HLL languages.

and COM object itself in case of HLL are always on heap, in assembly if object must be single instance - we are free to locate it in glodal memory of data section, and we could initialize it in design time like ClassFactory.
Post 13 Apr 2023, 07:32
View user's profile Send private message Send e-mail Reply with quote
mns



Joined: 20 Dec 2007
Posts: 150
Location: Piliyandala,Sri lanka
mns 13 Apr 2023, 09:23
Let us say I do this in data section
section '.data' data readable
myClassFactory dd myClassFactory_QueryInterface,myClassFactory_AddRef,myClassFactory_Release,myClassFactory_CreateInstance

and Implement each method in code section
section '.code' code readable executable
myClassFactory_QueryInterface:
;code here
ret
;----------------------------------------------------------------------------------------------------------

myClassFactory_AddRef:
;code here
ret
;----------------------------------------------------------------------------------------------------------

myClassFactory_Release:
;code here
ret
;----------------------------------------------------------------------------------------------------------

myClassFactory_CreateInstance :
;code here
ret

How can I initialize the myClassFactory object to use QueryInterface method in the DllGetClassObject function? (if I being foolish here please bare with me)
Post 13 Apr 2023, 09:23
View user's profile Send private message Send e-mail Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 804
Location: Russian Federation, Sochi
ProMiNick 13 Apr 2023, 10:01
for DllGetClassObject all thou described is enought. will be returned COM object myClassFactory.
Post 13 Apr 2023, 10:01
View user's profile Send private message Send e-mail Reply with quote
mns



Joined: 20 Dec 2007
Posts: 150
Location: Piliyandala,Sri lanka
mns 13 Apr 2023, 10:32
And call to
comcall myClassFactory_object, myClassFactory ,myClassFactory_CreateInstance,pUnkOuter,riid,ppvObject" (in DllGetClassObject function)
should return address of myClass in ppvObject?
Post 13 Apr 2023, 10:32
View user's profile Send private message Send e-mail Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 804
Location: Russian Federation, Sochi
ProMiNick 13 Apr 2023, 11:30
yes.

when thou call CoCreateInstance then OS enumerated calls to DllGetClassObject of all registered DLLs(registered as COM server).
If DllGetClassObject succesfuly returns ClassFactory, then OS runs its method CreateInstance, result of such call is COM oject. After that ClassFactory is released and created COM object returned to code called CoCreateInstance.
Post 13 Apr 2023, 11:30
View user's profile Send private message Send e-mail Reply with quote
mns



Joined: 20 Dec 2007
Posts: 150
Location: Piliyandala,Sri lanka
mns 13 Apr 2023, 13:07
Thank you very much ProMiNick now I understand. Very Happy
Post 13 Apr 2023, 13:07
View user's profile Send private message Send e-mail Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 804
Location: Russian Federation, Sochi
ProMiNick 13 Apr 2023, 13:21
"Thank" not grabbed to wallet. joke. As a payment I accept couple more of examples (in addition to mine 2s) of COM DLL published for that community (I`m ready to continue help on that way).
Post 13 Apr 2023, 13:21
View user's profile Send private message Send e-mail Reply with quote
mns



Joined: 20 Dec 2007
Posts: 150
Location: Piliyandala,Sri lanka
mns 14 Apr 2023, 11:29
Thanks. I will try. And for the first one, below shows my completed code(except
DllRegisterServer and DllUnregisterServer implementations). Hope there will be no errors
Code:
format PE GUI 4.0  DLL
entry startDLL


 include 'WIN32A.inc'
 ;include 'rcWin32p16.inc'
   struct GUID
       Data1 dd ?
       Data2 dw ?
       Data3 dw ?
       Data4 db 8 dup(?)
  ends



  ;objects
    struct   MYINTERFACEFactory
             QueryInterface             dd ?
             AddRef                     dd ?
             Release                    dd ?
             CreateInstance             dd ?
             LockServer                 dd ?

    ends
    struct   MYINTERFACE
             QueryInterface             dd ?
             AddRef                     dd ?
             Release                    dd ?
             GetMsgBox                  dd ?
             GetErrorMsgBox             dd ?
    ends

;/////////////////////////////////////////////////////////////////////////////////////////////////////
 section '.data' data readable writeable
;========================================================================================================
 myMSGBOXHead    db 'Error MSGBOX Heading',0
 myError         db 'This is a error',0
 mytext          db 'This is a test text',0
 modulename      db 1024 dup(?)

 CLSID_myInterfaceFactory GUID 0x4519ebca,0x1469,0x4fab,<0x88,0x48,0x5e,0xaf,0x4b,0xfb,0xbe,0x39>
 IID_myInterfaceFactory GUID 0xe1828e00,0xfa2d,0x41b5,<0x8c,0xf9,0x7d,0x22,0xd9,0x4c,0x56,0x38>
 IID_myInterface GUID 0x7218f11d,0x86ef,0x4344,<0x8e,0x96,0x60,0x31,0x94,0x21,0xf6,0xc6>

 IID_IUnknown   GUID 0x00000000,0x0000,0x0000,<0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46>
 IID_IClassFactory   GUID 0x00000001,0x0000,0x0000,<0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46>

 myInterfaceFactory    MYINTERFACEFactory    myIntrfcFtry_QueryInterface,myIntrfcFtry_AddRef,myIntrfcFtry_Release,myIntrfcFtry_CreateInstance,myIntrfcFtry_LockServer
 myInterface    MYINTERFACE  myInterface_QueryInterface,myInterface_AddRef,myInterface_Release,myInterface_GetMsgBox,myInterface_GetErrorMsgBox

 align 4
 MyObjCount    dd 0
 DllHinst      dd 0
 ;MyIntrfaceCount   dd 0
;======================================================================================================
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;/////////////////////////////////////////////////////////////////////////////////////////////////////
 section '.code' code readable executable
;======================================================================================================
;----------------------------------Entry point--------------------------------------------------------
   proc         startDLL  hInstance,Reason,Reserved
        push         [hInstance]
        pop          [DllHinst]
        mov          eax,TRUE
        ret

   endp
;---------------------DllGetClassObject------------------------------------------------------------------
   proc         DllGetClassObject stdcall uses ebx esi edi,rclsid,riid,ppv
        cmp         [ppv],0
        je          .emptyPointer
        mov         edi,[ppv]
        mov         dword[edi],0
        stdcall     compareGUIDs,CLSID_myInterfaceFactory,[rclsid]
        cmp         eax,0
        jne         .classNotAvailable

        stdcall     myIntrfcFtry_QueryInterface,[riid],[ppv]
        xor         eax,eax
        ret

   .emptyPointer:
        mov         eax,0x80004003 ;E_POINTER
        ret

   .classNotAvailable:
        mov         eax,80040154h  ; CLASS_E_CLASSNOTAVAILABLE
        ret
   endp


;---------------------DllCanUnloadNow------------------------------------------------------------------
   proc         DllCanUnloadNow stdcall uses ebx esi edi
        xor         eax,eax
        cmp         [MyObjCount],0
        jne         .canntUnload
        ret

   .canntUnload:
        mov         eax,1      ;S_FALSE
        ret
   endp

;---------------------DllRegisterServer------------------------------------------------------------------
   proc         DllRegisterServer stdcall uses ebx esi edi
        ;invoke      GetModuleFileName,[DllHinst],modulename,1024

        ret
   endp


;---------------------DllUnregisterServer------------------------------------------------------------------
   proc         DllUnregisterServer stdcall uses ebx esi edi

        ret
   endp


;--------------Methods of myInterfaceFactory------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------
   proc         myIntrfcFtry_QueryInterface stdcall uses ebx esi edi,riid,ppv
        cmp          [ppv],0
        je           .emptyPointer
        mov          edi,[ppv]
        mov          dword[edi],0
        stdcall      compareGUIDs,IID_IUnknown,[riid]
        cmp          eax,0
        je           .validIntrfc
        stdcall      compareGUIDs,IID_IClassFactory,[riid]
        cmp          eax,0
        jne          .noInterface

   .validIntrfc:
        mov          eax,myInterfaceFactory
        mov          [ppv],eax
        stdcall      myIntrfcFtry_AddRef
        xor          eax,eax
        ret



   .emptyPointer:
        mov          eax,0x80004003 ;E_POINTER
        ret


   .noInterface:
        mov          eax,0x80004002;E_NOINTERFACE
        ret
   endp
;----------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------
   proc         myIntrfcFtry_AddRef stdcall uses ebx esi edi
        ;inc     [MyObjCount]

        invoke       InterlockedIncrement,MyObjCount
        mov          eax,[MyObjCount]
        ret
   endp
;----------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------
   proc         myIntrfcFtry_Release stdcall uses ebx esi edi
       cmp           [MyObjCount],0
       je            .delObjct

       invoke        InterlockedDecrement,MyObjCount
       cmp           [MyObjCount],0
       jne           .returnRelease

    .delObjct:

       ;***need to delete the object here***


     .returnRelease:
         ret
    endp
;----------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------
   proc         myIntrfcFtry_CreateInstance stdcall uses ebx esi edi,pUnkOuter,riid,ppvObject

        cmp          [pUnkOuter],0
        jne          .nonAggregation
        cmp          [ppvObject],0
        je           .emptyPointer
        mov          edi,[ppvObject]
        mov          dword[edi],0
        stdcall      myInterface_QueryInterface,[riid],[ppvObject];
        ret

   .emptyPointer:
        mov          eax,0x80004003 ;E_POINTER
        ret
   .nonAggregation:
        mov          eax,0x80040110;CLASS_E_NOAGGREGATION;
        ret
   endp
;----------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------
   proc         myIntrfcFtry_LockServer stdcall uses ebx esi edi,fLock
        cmp          [fLock],0
        je           .freeLk
        invoke       InterlockedIncrement,MyObjCount
        xor          eax,eax
        ret

   .freeLk:
        invoke        InterlockedDecrement,MyObjCount
        xor          eax,eax
        ret
   endp
;----------------------------------------------------------------------------------------------------------






;--------------Methods of myInterface------------------------------------------------------------

;----------------------------------------------------------------------------------------------------------
   proc         myInterface_QueryInterface stdcall uses ebx esi edi,riid,ppv
        cmp          [ppv],0
        je           .emptyPointer
        mov          edi,[ppv]
        mov          dword[edi],0
        stdcall      compareGUIDs,IID_myInterface,[riid]
        cmp          eax,0
        jne          .noInterface

   .validIntrfc:
        mov          eax,myInterface
        mov          [ppv],eax
        stdcall      myInterface_AddRef
        xor          eax,eax
        ret



   .emptyPointer:
        mov          eax,0x80004003 ;E_POINTER
        ret


   .noInterface:
        mov          eax,0x80004002;E_NOINTERFACE
        ret
   endp

;----------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------
   proc         myInterface_AddRef stdcall uses ebx esi edi
        ;inc     [MyObjCount]

        invoke       InterlockedIncrement,MyObjCount
        mov          eax,[MyObjCount]
        ret
   endp
;----------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------
   proc         myInterface_Release stdcall uses ebx esi edi
       cmp           [MyObjCount],0
       je            .delObjct

       invoke        InterlockedDecrement,MyObjCount
       cmp           [MyObjCount],0
       jne           .returnRelease

    .delObjct:

       ;***need to delete the object here***


     .returnRelease:
         ret
    endp
;----------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------
   proc          myInterface_GetErrorMsgBox stdcall uses ebx esi edi
        lea             eax,[myError]
        lea             edx,[myMSGBOXHead]
        invoke          MessageBox, 0,eax,edx, MB_OK

        ret
    endp
;----------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------
   proc         myInterface_GetMsgBox  stdcall uses ebx esi edi
        lea             eax,[mytext]
        lea             edx,[myMSGBOXHead]
        invoke          MessageBox, 0,eax,edx, MB_OK

        ret
    endp
;----------------------------------------------------------------------------------------------------------


;--------------------------compareGUIDs------------------------------------------------------------------
   proc         compareGUIDs stdcall uses ebx esi edi,localGUID,outsideGUID

        mov             edi,[localGUID]
        mov             esi,[outsideGUID]
        cld
        cmpsd
        jne             .notIdentical
        cmpsw
        jne             .notIdentical
        cmpsw
        jne             .notIdentical
        mov             ecx,8
        repe            cmpsb
        jne             .notIdentical
        mov             eax,0
        ret

      .notIdentical:
        mov             eax,1
        ret

   endp




;==========================================================================================================
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;/////////////////////////////////////////////////////////////////////////////////////////////////////
 section '.idata' import data readable
;=======================================================================================================
 library    kernel32,'kernel32.dll',\
            user32,'USER32.DLL'

 include 'api/kernel32.inc'
 include 'api/USER32.inc'

;=======================================================================================================
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;/////////////////////////////////////////////////////////////////////////////////////////////////////
 section '.edata' export data readable
;=======================================================================================================

    export 'dlltest2.dll',\
            DllGetClassObject,'DllGetClassObject',\
            DllCanUnloadNow,'DllCanUnloadNow',\
            DllRegisterServer,'DllRegisterServer',\
            DllUnregisterServer,'DllUnregisterServer'

;=======================================================================================================
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;/////////////////////////////////////////////////////////////////////////////////////////////////////
section '.reloc' fixups data readable discardable
;=======================================================================================================
  if $=$$
    dd 0,8              ; if there are no fixups, generate dummy entry
  end if
;=======================================================================================================
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

    


Description:
Download
Filename: dlltest2.ASM
Filesize: 13.28 KB
Downloaded: 261 Time(s)

Post 14 Apr 2023, 11:29
View user's profile Send private message Send e-mail Reply with quote
mns



Joined: 20 Dec 2007
Posts: 150
Location: Piliyandala,Sri lanka
mns 25 Apr 2023, 10:58
This is the corrected example dll and testing program
This is the DLL
Code:
format PE GUI 4.0  DLL
entry startDLL


 include 'WIN32AX.inc'
 ;include 'custmFnc/win32Strfunc.inc'
   struct GUID
       Data1 dd ?
       Data2 dw ?
       Data3 dw ?
       Data4 db 8 dup(?)
  ends



  ;objects
    struct   IclassFactory
             QueryInterface             dd ?
             AddRef                     dd ?
             Release                    dd ?
             CreateInstance             dd ?
             LockServer                 dd ?

    ends
    struct   MYINTERFACE
             QueryInterface             dd ?
             AddRef                     dd ?
             Release                    dd ?
             GetMsgBox                  dd ?
             GetErrorMsgBox             dd ?
    ends

    ;struct   IclassFactoryObj
            ; IclassFactory_vtbl    IclassFactory
    ;ends

    struct   MYINTERFACEObj
             MYINTERFACE_vtbl         dd ?
             Refcounter               dd ?
    ends

;/////////////////////////////////////////////////////////////////////////////////////////////////////
 section '.data' data readable writeable
;========================================================================================================
 myMSGBOXHead    db 'MSGBOX Heading',0
 myError         db 'This is the error text',0
 mytext          db 'This is the text',0
 myInterfaceFactoryGUID_regText db 'Software\\Classes\\CLSID\\{4519ebca-1469-4fab-8848-5eaf4bfbbe39}',0
 CLSIDRegkeyText                db 'Software\\Classes\\CLSID',0
 MyIntfcGUIDText                db '{4519ebca-1469-4fab-8848-5eaf4bfbbe39}',0
 InprocServer32Text             db 'InprocServer32',0
 ThreadingModelText             db 'ThreadingModel',0
 bothText                       db 'both',0
 DLLRegError                    db 'Failed to register IExample.DLL as a COM component.',0
 modulename      db 1024 dup(?)

 CLSID_myInterface  GUID 0x4519ebca,0x1469,0x4fab,<0x88,0x48,0x5e,0xaf,0x4b,0xfb,0xbe,0x39>
 ;IID_myInterfaceFactory GUID 0xe1828e00,0xfa2d,0x41b5,<0x8c,0xf9,0x7d,0x22,0xd9,0x4c,0x56,0x38>
 IID_myInterface GUID 0x7218f11d,0x86ef,0x4344,<0x8e,0x96,0x60,0x31,0x94,0x21,0xf6,0xc6>

 IID_IUnknown   GUID 0x00000000,0x0000,0x0000,<0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46>
 IID_IClassFactory   GUID 0x00000001,0x0000,0x0000,<0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46>
 align 4
 ;myClassFactoryObj      IclassFactoryObj

 myClassFactory   IclassFactory     myIntrfcFtry_QueryInterface,myIntrfcFtry_AddRef,myIntrfcFtry_Release,myIntrfcFtry_CreateInstance,myIntrfcFtry_LockServer
 myInterface    MYINTERFACE  myInterface_QueryInterface,myInterface_AddRef,myInterface_Release,myInterface_GetMsgBox,myInterface_GetErrorMsgBox

 myInterfaceObj dd  myInterface
                dd  0      ;count

 myClassFactoryObj dd myClassFactory

 lockCount     dd 0
 MyObjCount    dd 0
 DllHinst      dd 0
 hKey          dd 0
 hKey2         dd 0
 disposition   dd 0
 ;MyIntrfaceCount   dd 0
;======================================================================================================
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;/////////////////////////////////////////////////////////////////////////////////////////////////////
 section '.code' code readable executable
;======================================================================================================
;----------------------------------Entry point--------------------------------------------------------
   proc         startDLL  hInstance,Reason,Reserved
        push         [hInstance]
        pop          [DllHinst]
        mov          eax,TRUE
        ret

   endp
;---------------------DllGetClassObject------------------------------------------------------------------
   proc         DllGetClassObject stdcall uses ebx esi edi,rclsid,riid,ppv
        cmp         [ppv],0
        je          .emptyPointer
        mov         edi,[ppv]
        mov         dword[edi],0
        stdcall     compareGUIDs,CLSID_myInterface,[rclsid]
        cmp         eax,0
        jne         .classNotAvailable

        stdcall     myIntrfcFtry_QueryInterface,myClassFactoryObj,[riid],[ppv]
        jmp         .ret_DllGetClassObject

   .emptyPointer:
        mov         eax,0x80004003 ;E_POINTER
        jmp         .ret_DllGetClassObject

   .classNotAvailable:
        mov         eax,80040154h  ; CLASS_E_CLASSNOTAVAILABLE

   .ret_DllGetClassObject:
        ret
   endp


;---------------------DllCanUnloadNow------------------------------------------------------------------
   proc         DllCanUnloadNow stdcall uses ebx esi edi

        xor         eax,eax
        cmp         [MyObjCount],0
        jne         .canntUnload
        ret

   .canntUnload:
        mov         eax,1      ;S_FALSE
        ret
   endp




;--------------Methods of IclassFactory------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------
   proc         myIntrfcFtry_QueryInterface stdcall uses ebx esi edi,ClassObjAddress,riid,ppv
        ;invoke      MessageBox, 0,'myIntrfcFtry_QueryInterface',0, MB_OK
        cmp          [ppv],0
        je           .emptyPointer
        mov          edi,[ppv]
        mov          dword[edi],0
        stdcall      compareGUIDs,IID_IUnknown,[riid]
        cmp          eax,0
        je           .validIntrfc

        stdcall      compareGUIDs,IID_IClassFactory,[riid]
        cmp          eax,0
        jne          .noInterface


   .validIntrfc:

        mov          eax,myClassFactoryObj
        mov          dword[edi],eax
        stdcall      myIntrfcFtry_AddRef,eax;[ClassObjAddress]
        xor          eax,eax
        ret



   .emptyPointer:
        mov          eax,0x80004003 ;E_POINTER
        ret


   .noInterface:
        mov          eax,0x80004002;E_NOINTERFACE
        ret
   endp
;----------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------
   proc         myIntrfcFtry_AddRef stdcall uses ebx esi edi,ClassObjAddress
        ;invoke      MessageBox, 0,'myIntrfcFtry_AddRef',0, MB_OK
        invoke        InterlockedIncrement,MyObjCount;
        mov           eax,1
       ret
   endp
;----------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------
   proc         myIntrfcFtry_Release stdcall uses ebx esi edi,ClassObjAddress
        ;invoke      MessageBox, 0,'myIntrfcFtry_Release',0, MB_OK
        invoke        InterlockedDecrement,MyObjCount;
        mov           eax,[MyObjCount]
        ret
    endp
;----------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------
   proc         myIntrfcFtry_CreateInstance stdcall uses ebx esi edi,ClassObjAddress,pUnkOuter,riid,ppvObject
        ;invoke      MessageBox, 0,'myIntrfcFtry_CreateInstance',0, MB_OK

        ;stdcall         GUIDToStrng,CLSID_myInterfaceFactory,1
        cmp          [pUnkOuter],0
        jne          .nonAggregation
        cmp          [ppvObject],0
        je           .emptyPointer
        mov          edi,[ppvObject]
        mov          dword[edi],0
        mov          [myInterfaceObj+4],1
        stdcall      myInterface_QueryInterface,myInterfaceObj,[riid],[ppvObject];
        cmp          eax,0
        jne          .failed
        mov          edi,myInterfaceObj
        add          edi,4
        ;stdcall     ValueToHxDcmlStrng,edi,1

        stdcall      myInterface_Release,myInterfaceObj
        ;invoke      MessageBox, 0,'finish release',0, MB_OK

        xor          eax,eax
        ret

   .failed:
        ;stdcall      myInterface_Release,myInterfaceObj
        invoke        InterlockedDecrement,MyObjCount;
        mov          eax,0x80004005
        ret

   .emptyPointer:
        mov          eax,0x80004003 ;E_POINTER
        ret

   .nonAggregation:
        mov          eax,0x80040110;CLASS_E_NOAGGREGATION;
        ret
   endp
;----------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------
   proc         myIntrfcFtry_LockServer stdcall uses ebx esi edi,fLock
        ;invoke      MessageBox, 0,'myIntrfcFtry_LockServer',0, MB_OK
        cmp          [fLock],0
        je           .freeLk
        invoke       InterlockedIncrement,lockCount
        xor          eax,eax
        ret

   .freeLk:
        invoke       InterlockedDecrement,lockCount
        xor          eax,eax
        ret
   endp
;----------------------------------------------------------------------------------------------------------






;--------------Methods of myInterface------------------------------------------------------------

;----------------------------------------------------------------------------------------------------------
   proc         myInterface_QueryInterface stdcall uses ebx esi edi,IntrfcObjAddress,riid,ppv
        ;invoke      MessageBox, 0,'QueryInterface',0, MB_OK
        cmp          [ppv],0
        je           .emptyPointer
        mov          edi,[ppv]
        mov          dword[edi],0
        stdcall      compareGUIDs,IID_IUnknown,[riid]
        cmp          eax,0
        je           .validIntrfc
        stdcall      compareGUIDs,IID_myInterface,[riid]
        cmp          eax,0
        jne          .noInterface

   .validIntrfc:
        mov          eax,myInterfaceObj
        mov          dword[edi],eax
        stdcall      myInterface_AddRef,eax
        xor          eax,eax
        jmp          .ret__QueryInterface



   .emptyPointer:
        mov          eax,0x80004003 ;E_POINTER
        jmp          .ret__QueryInterface


   .noInterface:
        mov          eax,0x80004002;E_NOINTERFACE

   .ret__QueryInterface:
        ret
   endp

;----------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------
   proc         myInterface_AddRef stdcall uses ebx esi edi,IntrfcObjAddress
      ;inc     [MyObjCount]
      ;invoke      MessageBox, 0,'AddRef',0, MB_OK
       mov           edi,dword[IntrfcObjAddress]
       add           edi,4
       invoke       InterlockedIncrement,edi
       mov          eax,dword[edi]
       ret
   endp
;----------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------
   proc         myInterface_Release stdcall uses ebx esi edi,IntrfcObjAddress
       ;invoke      MessageBox, 0,'Release',0, MB_OK
       mov           edi,dword[IntrfcObjAddress]
       add           edi,4
       ;stdcall     ValueToHxDcmlStrng,edi,1
       invoke        InterlockedDecrement,edi
       cmp           dword[edi],0
       jne           .returnRelease

    .delObjct:

       ;***need to delete the object here if object was allocated memory from heap***
       invoke        InterlockedDecrement,MyObjCount;


     .returnRelease:
        mov          eax,dword[edi]
        ret
    endp
;----------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------
   proc          myInterface_GetErrorMsgBox stdcall uses ebx esi edi,IntrfcObjAddress
        ;invoke      MessageBox, 0,'GetErrorMsgBox',0, MB_OK
        lea             eax,[myError]
        lea             edx,[myMSGBOXHead]
        invoke          MessageBox, 0,eax,edx, MB_OK

        ret
    endp
;----------------------------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------
   proc         myInterface_GetMsgBox  stdcall uses ebx esi edi,IntrfcObjAddress
        ;invoke      MessageBox, 0,'GetMsgBox',0, MB_OK
        lea             eax,[mytext]
        lea             edx,[myMSGBOXHead]
        invoke          MessageBox, 0,eax,edx, MB_OK

        ret
    endp
;----------------------------------------------------------------------------------------------------------


;--------------------------compareGUIDs------------------------------------------------------------------
   proc         compareGUIDs stdcall uses ebx esi edi,localGUID,outsideGUID

        mov             edi,[localGUID]
        mov             esi,[outsideGUID]
        cld
        cmpsd
        jne             .notIdentical
        cmpsw
        jne             .notIdentical
        cmpsw
        jne             .notIdentical
        mov             ecx,8
        repe            cmpsb
        jne             .notIdentical
        mov             eax,0
        ret

      .notIdentical:
        mov             eax,1
        ret

   endp




;==========================================================================================================
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;/////////////////////////////////////////////////////////////////////////////////////////////////////
 section '.idata' import data readable
;=======================================================================================================
 library    kernel32,'kernel32.dll',\
            user32,'USER32.DLL',\
            ADVAPI32,'ADVAPI32.DLL'



 include 'api/advapi32.inc'
 include 'api/kernel32.inc'
 include 'api/USER32.inc'


;=======================================================================================================
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;/////////////////////////////////////////////////////////////////////////////////////////////////////
 section '.edata' export data readable
;=======================================================================================================

    export 'dlltest2.dll',\
            DllGetClassObject,'DllGetClassObject',\
            DllCanUnloadNow,'DllCanUnloadNow'

;=======================================================================================================
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;/////////////////////////////////////////////////////////////////////////////////////////////////////
section '.reloc' fixups data readable discardable
;=======================================================================================================
  if $=$$
    dd 0,8              ; if there are no fixups, generate dummy entry
  end if
;=======================================================================================================
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
    



This is the test programme

Code:
format PE GUI 4.0
entry start


 include 'WIN32AX.inc'
 include 'testREGRc.inc'
 ;include 'DxInclds/objbase.inc'
 ;include 'custmFnc/win32Strfunc.inc'
   struct GUID
       Data1 dd ?
       Data2 dw ?
       Data3 dw ?
       Data4 db 8 dup(?)
  ends
   interface   IclassFactory,\
             QueryInterface,\
             AddRef,\
             Release,\
             CreateInstance,\
             LockServer

   interface  MYINTERFACE,\
             QueryInterface,\
             AddRef,\
             Release,\
             GetMsgBox,\
             GetErrorMsgBox

;/////////////////////////////////////////////////////////////////////////////////////////////////////
 section '.data' data readable
;========================================================================================================
    CLSCTX_INPROC_SERVER  = 0x1
    COINIT_APARTMENTTHREADED  = 0x2
    COINIT_DISABLE_OLE1DDE    = 0x4


    MenuName            = IDR_MAINMENU
    ClassName           db 'MNSwndClass',0
    AppName             db 'window Ideal',0

    ButtonClassName     db 'BUTTON',0
    ButtonText1        db 'Get ErrorTX',0
    ButtonText2        db 'Get TX',0

  ;------------------error texts---------------------------------------
    ErrTxt1             db 'Registering window class Failed',0
    ErrTxt2             db 'Fail to create a window using MNSwndClass',0
    ErrTxt3             db 'Error in the message loop of the window',0
    ErrTxt4             db 'COM library could not initialized',0
    ErrTxt5             db 'Myclass Factory object could not created',0
    ErrMsgBoxCaption    db 'Program Error',0
    WindowProcErrTxt1   db 'Error in creation of Child control',0
    WindowProcErrTxt2   db 'cocreate failed',0
    ;WindowProcErrTxt3   db 'Creat process failed',0
    ;WindowProcErrTxt4   db 'Error reading',0
    DLLRegError         db 'Error in creation Registry Entries',0
    myMSGBOXHead        db 'RegCreate',0

   myInterfaceFactoryGUID_regText db 'Software\\Classes\\CLSID\\{4519ebca-1469-4fab-8848-5eaf4bfbbe39}',0
 CLSIDRegkeyText                db 'Software\\Classes\\CLSID',0
 MyIntfcGUIDText                db '{4519ebca-1469-4fab-8848-5eaf4bfbbe39}',0
 InprocServer32Text             db 'InprocServer32',0
 ThreadingModelText             db 'ThreadingModel',0
 bothText                       db 'both',0
 dllName                        db 'dlltest3.DLL',0

 CLSID_myInterface   GUID 0x4519ebca,0x1469,0x4fab,<0x88,0x48,0x5e,0xaf,0x4b,0xfb,0xbe,0x39>
 IID_IClassFactory   GUID 0x00000001,0x0000,0x0000,<0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46>
 IID_myInterface     GUID 0x7218f11d,0x86ef,0x4344,<0x8e,0x96,0x60,0x31,0x94,0x21,0xf6,0xc6>
 ;CLSID_myInterfaceFactory_string   db  '4519ebca-1469-4fab-8848-5eaf4bfbbe39',0
 ;IID_myInterfaceFactory_string     db  'e1828e00-fa2d-41b5-8cf9-7d22d94c5638',0
;/////////////////////////////////////////////////////////////////////////////////////////////////////
 section '.?data' data readable writeable
;========================================================================================================
  myFactoryObj         IclassFactory
  myIntrFcObj          MYINTERFACE

    msg                 MSG
    wc                  WNDCLASSEX
    cmdLine             dd ?
    hInst               dd ?
    hwnd                dd ?
    ;hEdit               dd ?
    hwndButton1         dd 0
    hwndButton2         dd 0
    hwndButton3         dd 0
    hwndButton4         dd 0
    DllHinst      dd 0
 hKey          dd 0
 hKey2         dd 0
 disposition   dd 0
 modulename      db 1024 dup(?)
;//////////////////////////////////////////////////////////

;/////////////////////////////////////////////////////////////////////////////////////////////////////
 section '.code' code readable executable
;=====================================================================================================
   start:
       invoke      GetModuleHandle,0
       mov         [hInst],eax
       invoke      GetCommandLine
       mov         [cmdLine],eax
       stdcall     WinMain,[hInst],NULL,[cmdLine],SW_SHOWDEFAULT
       stdcall     DllUnregisterServer
       invoke      ExitProcess,eax

;-----------------------WinMain Procedure-------------------------------------------------------------
   proc WinMain   hInstance:DWORD,hPrvinstance:DWORD,commandLine:DWORD,cmdshow:DWORD
        ;stdcall         GUIDToStrng,CLSID_myInterfaceFactory,1

        stdcall         DllRegisterServer
        invoke          CoInitializeEx,NULL,COINIT_APARTMENTTHREADED + COINIT_DISABLE_OLE1DDE
        cmp             eax,0
        jne             err4

        invoke          CoCreateInstance,CLSID_myInterface,0,CLSCTX_INPROC_SERVER,IID_myInterface,myIntrFcObj
        ;invoke          CoGetClassObject,CLSID_myInterface, CLSCTX_INPROC_SERVER, 0, IID_IClassFactory,myFactoryObj;
        cmp             eax,0
        jne             err5
        ;cominvk         myFactoryObj,CreateInstance,0, IID_myInterface, myIntrFcObj
        ;cmp             eax,0
        ;jne             err5
        ;invoke          MessageBox, 0,'success',ErrMsgBoxCaption, MB_OK

       ;----declare window struct----------------------------
         push        [hInst]
         pop         [wc.hInstance]
         mov         [wc.cbSize], sizeof.WNDCLASSEX
         mov         [wc.style], CS_HREDRAW or CS_VREDRAW
         mov         [wc.lpfnWndProc],WindowProc
         xor         eax,eax
         mov         [wc.cbClsExtra],eax
         mov         [wc.cbWndExtra],eax
         mov         [wc.hbrBackground], COLOR_APPWORKSPACE
         mov         [wc.lpszMenuName], MenuName
         mov         [wc.lpszClassName],ClassName
         invoke      LoadIcon, NULL, IDI_APPLICATION
         mov         [wc.hIcon], eax
         mov         [wc.hIconSm], eax
         invoke      LoadCursor, NULL, IDC_ARROW
         mov         [wc.hCursor], eax

       ;----Registering window class----------
         invoke      RegisterClassEx, wc
         or          eax,eax
         jz          err1;end_loop

       ;----Create a window-------------------
         invoke      CreateWindowEx,WS_EX_CLIENTEDGE,ClassName,AppName,WS_VISIBLE+WS_OVERLAPPED+WS_CAPTION+WS_SYSMENU+WS_MINIMIZEBOX+WS_MAXIMIZEBOX,CW_USEDEFAULT,CW_USEDEFAULT,200,300,0,0,[wc.hInstance],0
         mov         [hwnd],eax
         or          eax,eax
         jz          err2;end_loop

       ;-----Show window----------------------
         invoke      ShowWindow, [hwnd],[cmdshow]

       ;-----Update window---------------------
         invoke      UpdateWindow, [hwnd]

       ;-----message loop----------------------
         msg_loop:
              invoke      GetMessage,msg,NULL,0,0
              cmp         eax,0
              je          end_loop
              jb          err3
              invoke      TranslateMessage,msg
              invoke      DispatchMessage,msg
              jmp         msg_loop

        ;-------------Errors--------------------------------------------
         err1:
              invoke      MessageBox, 0,ErrTxt1,ErrMsgBoxCaption, MB_OK
              jmp         end_loop
         err2:
              invoke      MessageBox, 0,ErrTxt2,ErrMsgBoxCaption, MB_OK
              jmp         end_loop
         err3:
              invoke      MessageBox, 0,ErrTxt3,ErrMsgBoxCaption, MB_OK
              jmp         end_loop
         err4:
              invoke      MessageBox, 0,ErrTxt4,ErrMsgBoxCaption, MB_OK
              jmp         end_loop
         err5:
              ;stdcall     ValueToHxDcmlStrng,eax,1
              invoke      MessageBox, 0,ErrTxt5,ErrMsgBoxCaption, MB_OK
              ;jmp         end_loop
        ;---------------------------------------------------------------

         end_loop:
              stdcall     CleanALL
              invoke      CoUninitialize
              mov         eax,[msg.wParam]
              ret
   endp

;----------------------------------------------------------------------------------------------------------

;------------------------------------window procedure------------------------------------------------------
   proc       WindowProc hwnds,umsg:DWORD,wParam:DWORD,iParam:DWORD

              push             ebx esi edi
              cmp              [umsg],WM_DESTROY
              je               wmdestroy
              cmp              [umsg],WM_COMMAND
              je               commands
              cmp              [umsg],WM_CREATE
              je               cerate

         defwndproc:
              invoke           DefWindowProc,[hwnds],[umsg],[wParam],[iParam]
              jmp              finish

         commands:
              cmp              [iParam],0
              jne              .otherCommands
              mov              eax,[wParam]
              cmp              ax,IDM_EXIT
              je               wmdestroy
              cmp              ax,IDM_HELP
              je               .helpMSG

              jmp              finish

          .helpMSG:
                 jmp              finish

          .otherCommands:
                 cmp              [wParam], BN_CLICKED shl 16 +IDB_BUTTON1
                 je               GeterrTxt ;DllRegisterServer
                 cmp              [wParam], BN_CLICKED shl 16 +IDB_BUTTON2
                 je               GetTextD ;DllUnregisterServer
                 jmp              finish

          GeterrTxt:
                cominvk         myIntrFcObj,GetErrorMsgBox
                jmp             finish

          GetTextD:
                cominvk         myIntrFcObj,GetMsgBox
                jmp             finish



          cerate:
               invoke          CreateWindowEx,0,ButtonClassName,ButtonText1,WS_CHILD + WS_VISIBLE + BS_DEFPUSHBUTTON,50,50,100,40,[hwnds],IDB_BUTTON1,[hInst],0
               cmp             eax,0
               je              WindowProc_error1
               mov             [hwndButton1],eax

               invoke          CreateWindowEx,0,ButtonClassName,ButtonText2,WS_CHILD + WS_VISIBLE + BS_DEFPUSHBUTTON,50,150,100,40,[hwnds],IDB_BUTTON2,[hInst],0
               cmp             eax,0
               je              WindowProc_error1
               mov             [hwndButton2],eax



               jmp             finish
        ;-------------Errors-------------------------------
         WindowProc_error1:
              invoke           MessageBox, 0,WindowProcErrTxt1,ErrMsgBoxCaption, MB_OK
              jmp              finish

        WindowProc_error2:
              invoke           MessageBox, 0,WindowProcErrTxt2,ErrMsgBoxCaption, MB_OK
              jmp              finish

         ;WindowProc_error3:
              ;invoke           MessageBox, 0,WindowProcErrTxt3,ErrMsgBoxCaption, MB_OK
              ;jmp              finish

         ;WindowProc_error4:
              ;invoke           MessageBox, 0,WindowProcErrTxt4,ErrMsgBoxCaption, MB_OK
              ;jmp              commands.terminateProcess


        ;--------------------------------------------------
         wmdestroy:
              invoke           PostQuitMessage,0
              xor              eax,eax

         finish:
              pop              edi esi ebx
              ret
   endp
;---------------------------------------------------------------------------------------------------------


;---------------------DllRegisterServer------------------------------------------------------------------
   proc         DllRegisterServer stdcall uses ebx esi edi
        ;1).Create a subkey whose name is the ascii string that represents our object's GUID
        ;so
        invoke      RegCreateKeyEx,HKEY_LOCAL_MACHINE, myInterfaceFactoryGUID_regText, 0, 0, REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, hKey, disposition
        cmp         eax,0
        jne         .err1
        ;2).Create an "InprocServer32" key whose default value is the path of this DLL
        invoke      RegCreateKeyEx,[hKey],InprocServer32Text, 0, 0, REG_OPTION_NON_VOLATILE, KEY_WRITE, 0,hKey2, disposition
        cmp         eax,0
        jne         .err2

        invoke      GetModuleFileName,[DllHinst],modulename,1024
        cmp         eax,0
        je          .err3
        mov         ecx,12
        sub         eax,10
        mov         edi,modulename
        add         edi,eax
        dec         edi
        add         eax,ecx           
        mov         esi,dllName
        cld
        rep         movsb



        invoke      RegSetValueEx,[hKey2], 0, 0, REG_SZ, modulename, eax
        cmp         eax,0
        jne         .err3

        ;3).Create a "ThreadingModel" value set to the string "both"

        invoke      RegSetValueEx,[hKey2], ThreadingModelText, 0, REG_SZ,bothText,5
        cmp         eax,0
        jne         .err3
        invoke      RegCloseKey,[hKey2]
        invoke      RegCloseKey,[hKey]
        invoke      MessageBox,0, 'DLL registered- OK',0, MB_OK;

        ret

   .err3:
        invoke      RegDeleteKey,[hKey2],InprocServer32Text
        invoke      RegCloseKey,[hKey2]

   .err2:
        invoke      RegDeleteKey,[hKey],myInterfaceFactoryGUID_regText
        invoke      RegCloseKey,[hKey]

   .err1:

        invoke      MessageBox,0, DLLRegError,myMSGBOXHead, MB_OK+MB_ICONEXCLAMATION;
        ret

   endp

;---------------------CleanALL------------------------------------------------------------------
   proc         CleanALL stdcall uses ebx esi edi
        cmp             [myIntrFcObj],0
        je              @f
        cominvk         myIntrFcObj, Release
        mov             [myIntrFcObj],0
     @@:
        xor             eax,eax
        ret
   endp

;---------------------------------------------------------------------------------------------------------


;---------------------DllUnregisterServer------------------------------------------------------------------
   proc         DllUnregisterServer stdcall uses ebx esi edi
        invoke      RegOpenKeyEx,HKEY_LOCAL_MACHINE,CLSIDRegkeyText, 0, KEY_WRITE,hKey
        cmp         eax,0
        jne         .retDLLUnreg
        invoke      RegOpenKeyEx,[hKey], MyIntfcGUIDText, 0, KEY_ALL_ACCESS,hKey2
        cmp         eax,0
        jne         .closeKey
        invoke      RegDeleteKey,[hKey2],InprocServer32Text
        invoke      RegCloseKey,[hKey2]
        invoke      RegDeleteKey,[hKey],MyIntfcGUIDText

   .closeKey:
        invoke      RegCloseKey,[hKey]

   .retDLLUnreg:
        invoke      MessageBox,0, 'DLL Un-registered -OK',0, MB_OK;

        xor        eax,eax
        ret
   endp


;==========================================================================================================
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;//////////////////////////////////////////////////////////

;//////////////////////////////////////////////////////////////////////////////////////////////////////
 section '.idata' import data readable
;=======================================================================================================
  library kernel32,'KERNEL32.DLL',\
           user32,'USER32.DLL',\
           comctl32,'comctl32.dll',\
            ADVAPI32,'ADVAPI32.DLL',\
           Ole32,'ole32.dll'



 include 'api/advapi32.inc'
  include 'api/comctl32.inc'
  include 'api/kernel32.inc'
  include 'api/USER32.inc'
  ;include 'DxInclds/Api/ole32.inc'
import  Ole32,\
  CoInitializeEx,'CoInitializeEx',\
  CoCreateInstance,'CoCreateInstance',\
  CoUninitialize,'CoUninitialize'

;=======================================================================================================
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
    


If anything wrong please post a reply


Description:
Download
Filename: testRegtr.zip
Filesize: 9.69 KB
Downloaded: 246 Time(s)

Post 25 Apr 2023, 10:58
View user's profile Send private message Send e-mail 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.