News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Err in dll

Started by askm, June 16, 2006, 10:32:46 PM

Previous topic - Next topic

askm

What's wrong with this dll ?

It may be OK, but if the object.Value(Set) statements are structured in a certain way, the output(Get) produces string errors.

Here is the main:


;-------------------------------------------------------------------------------
.code

DBGWIN_DEBUG_ON = 1 ;turn it off if you don't want to include debug info into the program
DBGWIN_EXT_INFO = 1 ;turn it off if you don't want to include extra debug info into the program

;-------------------------------------------------------------------------------
CreateMyCom3 PROC this_:DWORD

    LOCAL hMem:DWORD
    nop
    nop
    nop

    pObjectData this_, edx  ; cast this_ to object data
    push edx



    nop
    nop
    nop

    pop edx
    mov DWORD ptr DS:(MyCom3ObjData ptr [edx]).m_Str, 00650065h

    nop
    nop
    nop

    xor eax, eax                                ; return S_OK

    nop
    nop
    nop

    xor eax, eax                                ; return S_OK

    ret


CreateMyCom3 ENDP
;-------------------------------------------------------------------------------
GetValue PROC this_:DWORD, pStr:DWORD   ; GetValue for the IMyCom Interface
    nop
    nop
    db 0090h
    nop
    pObjectData this_, edx                      ; cast this_ to object data

    push ebx
    push ebp                    ; has to be done before changing ESP

push eax

    mov eax, (MyCom3ObjData ptr [edx]).m_Str  ; get object data value

    mov ecx, pStr                               ; get ptr to variable for return

    mov [ecx], eax

push ecx
push eax
sub eax, 4
mov ecx, eax
mov eax,ecx
add eax,00h
pop eax
pop ecx

pop eax

    xor eax, eax                                ; return S_OK

    nop
    nop
    nop

    ret
GetValue ENDP
;-------------------------------------------------------------------------------
SetValue PROC this_:DWORD, newStr:DWORD    ; SetValue for the IMyCom Interface

    nop
    nop
    nop

    pObjectData this_, edx  ; cast this_ to object data
push edx

push ebp
push esp
    nop
    nop
    nop



push esi
push edi
    mov eax, newStr                                ; get variable


    mov (MyCom3ObjData ptr [edx]).m_Str, eax  ; store new value   

    nop
    nop
    nop



pop edi
pop esi

pop esp
pop ebp

pop edx

    xor eax, eax
    ret
SetValue ENDP


;


Thank you for reading.

Ian_B

Well apart from all the bizarre NOPs and the pushing and popping of EBP/ESP which almost certainly isn't doing what you want it to (since it looks suspiciously like you're trying to create a stack frame manually which MASM does for you anyway by default), the biggest ringer is this line, which does nothing:

pObjectData this_, edx                      ; cast this_ to object data

There's no such thing as a "cast" in MASM, that's C terminology, a DWORD in a register can be anything you want it to be as long as it is consistent, the assembler doesn't care where it's come from or whether it's data or a pointer. In this line there's no assembler operation anyway. What you might mean is the MASM ASSUME syntax, which tells the assembler to treat a register as a pointer to a structure:

ASSUME EDX:pObjectData

assuming that pObjectData has previously been defined correctly as a structure in the .DATA section. You didn't actually move the "this_" value into the EDX register yet, though! That would then allow you to use the dotted sub-element notation which you use later, but also incorrectly:

mov eax, MyCom3ObjData[edx].m_Str  ; get object data value

assuming that m_Str is an element of the pObjectData structure and MyCom3ObjData is a defined memory location containing an array of such structures. Using the PTR syntax in the middle is incorrect. For that line to be meaningful EDX would have to be a multiple of the SIZEOF the structure, so you'd be pointing to a specific pObjectData structure in the array. If the EDX value is a pointer direct to your structure, then this line won't work. When you have finished with using EDX in this way, you must release the assumption with:

ASSUME EDX:NOTHING

otherwise following code will not assemble correctly. I'll leave it to others to pick apart the stack handling.

Ian_B

askm


So far, I have based it on the com\example MyCom's.
Thanks.

Casper

Also it does not conform to the structure of a DLL.

Casper

askm

Anyone's insight into Casper's structure statement ?

askm

Where's Ernest anyway ? He started it !

Ian_B

Quote from: Casper on June 17, 2006, 10:44:08 AM
Also it does not conform to the structure of a DLL.

This is true, but I'd have thought that was a problem to be solved once pseudocode had been replaced with actual workable code.

Askm, the info you need on constructing a DLL is here: http://website.masm32.com/dlltute/masmdll.htm - but you'll need to do a lot more work on the code before you get to that stage.

askm

Some of you may know the answer.
May it be in the stacks ?
Or cannot a SetValue reference itself ?

Casper

Okay a DLL MUST start like this...
DllEntry proc hInst:DWORD, reason:DWORD, reserved1:DWORD
;---------------------------------------;
        .if reason==DLL_PROCESS_ATTACH  ; When the dll is loaded
          push hInst
          pop hInstance
          call Main
        .endif
        mov eax,TRUE
        ret
;---------------------------------------
DllEntry Endp


You can rename Main to match your procedure.  A DLL must ALWAYS return True.

The two above steps are missing in your code.

At the end, you MUST put ...
        End     DllEntry


Casper

rags

He wouldn't necessarily have to call 'Main' in his entry proceedure or any other funtion for that matter would he?
Could'nt he just call the exported functions as needed?
Rags
God made Man, but the monkey applied the glue -DEVO

Casper

rags,
No, only if he wants the DLL to execute as soon as it is loaded by an application.  Otherwise there should be no call.  Thank you for reminding me that there is more than one type of DLL.

Casper

hutch--

Something sounds wrong with this description, you can load a DLL in a couple of ways, statically when the app starts or dynamically with LoadLibrary(), GetProcAddress() .... FreeLibrary() after but in either of these techniques you then must call the procedure you require. The DLLmain/LibMain or whatever you call the entry point proc is caled only by the OS, not the calling app. You uase it to set up any conditions you require before you call a procedure in the DLL.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

P1

Get & Set are COM callbacks, which are normally in a ocx ( a dll by another name ).

askm, 

Begin by going through COM tutorial and examples here.  You are way behind the learning curve and you need to catch up.  Also check out the "Custom Interface Components" here as well.

Learn Well, then Do Well !!!   :U

Regards,  P1  :8)

Casper

Hutch,
Please do not be offended.  I think you need to read up on CPL files.  They are actually DLLs.  This is from one that I have in my archive.

  include Protect.inc
  include Macros.asm
  include registry.asm
  include Dialogs.asm

CPlApplet PROTO :DWORD, :DWORD, :DWORD, :DWORD

.CODE

DllEntry proc hInst:HINSTANCE, reason:DWORD, reserved1:DWORD
;--------------------------------------
  .IF reason==DLL_PROCESS_ATTACH

    INVOKE GetModuleHandle, addr nameCPL ; NULL
    mov hInstance, eax

  .ENDIF

  mov  eax,TRUE
  ret
;--------------------------------------
DllEntry Endp


CPlApplet proc hWnd:DWORD, uMsg:DWORD, lParam1:DWORD, lParam2:DWORD
;--------------------------------------
  .IF uMsg == CPL_INIT

  .ELSEIF uMsg == CPL_GETCOUNT

    mov     eax, 1

  .ELSEIF uMsg == CPL_INQUIRE

    push    esi
    mov     esi, lParam2
    assume  esi:ptr CPLINFO
    mov     [esi].lData, 0
    mov     [esi].idIcon, 200
    mov     [esi].idName, 3000
    mov     [esi].idInfo, 3001
    assume  esi: nothing
    pop     esi

  .ELSEIF uMsg == CPL_DBLCLK

; Set up the 1st property sheet

    mov     PropSheet.dwSize, sizeof PROPSHEETPAGE
    m2m     PropSheet.dwFlags, PSP_DEFAULT + PSP_USEICONID
    m2m     PropSheet.hInstance, hInstance
    m2m     PropSheet.pszTemplate, offset mydb1
    mov     PropSheet.pszIcon, 201
    m2m     PropSheet.pfnDlgProc, offset DialogFunc1
    m2m     PropSheet.pszTitle, offset psztitle
    mov     PropSheet.lParam, 0
    mov     PropSheet.pfnCallback, 0

; Set up the 2nd property sheet

    mov     PropSheet[(sizeof PROPSHEETPAGE)].dwSize, sizeof PROPSHEETPAGE
    m2m     PropSheet[(sizeof PROPSHEETPAGE)].dwFlags, PSP_DEFAULT + PSP_USEICONID
    m2m     PropSheet[(sizeof PROPSHEETPAGE)].hInstance, hInstance
    m2m     PropSheet[(sizeof PROPSHEETPAGE)].pszTemplate, offset mydb2
    mov     PropSheet[(sizeof PROPSHEETPAGE)].pszIcon, 202
    m2m     PropSheet[(sizeof PROPSHEETPAGE)].pfnDlgProc, offset DialogFunc2
    m2m     PropSheet[(sizeof PROPSHEETPAGE)].pszTitle, offset psztitle
    mov     PropSheet[(sizeof PROPSHEETPAGE)].lParam, 0
    mov     PropSheet[(sizeof PROPSHEETPAGE)].pfnCallback, 0

; Set up the 3rd property sheet

    mov     PropSheet[(sizeof PROPSHEETPAGE)*2].dwSize, sizeof PROPSHEETPAGE
    m2m     PropSheet[(sizeof PROPSHEETPAGE)*2].dwFlags, PSP_DEFAULT + PSP_USEICONID
    m2m     PropSheet[(sizeof PROPSHEETPAGE)*2].hInstance, hInstance
    m2m     PropSheet[(sizeof PROPSHEETPAGE)*2].pszTemplate, offset mydb3
    mov     PropSheet[(sizeof PROPSHEETPAGE)*2].pszIcon, 203
    m2m     PropSheet[(sizeof PROPSHEETPAGE)*2].pfnDlgProc, offset DialogFunc3
    m2m     PropSheet[(sizeof PROPSHEETPAGE)*2].pszTitle, offset psztitle
    mov     PropSheet[(sizeof PROPSHEETPAGE)*2].lParam, 0
    mov     PropSheet[(sizeof PROPSHEETPAGE)*2].pfnCallback, 0

; Create the 3 Pages

    invoke  CreatePropertySheetPage, ADDR PropSheet
    mov     hPs, eax
    invoke  CreatePropertySheetPage, ADDR PropSheet[sizeof PROPSHEETPAGE]
    mov     hPs[4], eax
    invoke  CreatePropertySheetPage, ADDR PropSheet[(sizeof PROPSHEETPAGE)*2]
    mov     hPs[8], eax

; Set up the property sheet header

    mov     PropHdr.dwSize, sizeof PROPSHEETHEADERA
    mov     PropHdr.dwFlags, PSH_DEFAULT
    m2m     PropHdr.hwndParent,NULL     ;hWnd
    m2m     PropHdr.hInstance, hInstance
    mov     PropHdr.pszIcon, 0
    m2m     PropHdr.pszCaption, offset caption
    mov     PropHdr.nPages, 3
    mov     PropHdr.nStartPage, 0
    m2m     PropHdr.phpage, offset hPs
    mov     PropHdr.pfnCallback, 0

; Display the property sheet control

    invoke  PropertySheet, ADDR PropHdr

  .ELSEIF uMsg == CPL_STOP

    return  0

  .ELSEIF uMsg == CPL_EXIT

    return  1

  .ENDIF

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

END DllEntry


Casper

zooba

Casper,

I think you'll find that the DllEntry procedure doesn't call any other procedure or do any 'real' work. CPL files have to be started from, IIRC, control.exe, which will call CPlApplet. DllEntry is called as part of the LoadLibrary (or whatever is used).

Cheers,

Zooba :U