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

Casper

zooba,
You have missed the entrire point of the discussion.  The point Hutch is making is that there must be a caal statement in the DLL (a CPL file 'is' a DLL) as  follows:
Quoteyou then must call the procedure you require
As you can see in my code, there is no call to CPlApplet, which is the 'workhorse' of this DLL.  Don't worry about it, not many know about the CPL file and the fact that it is a DLL.  By the way, you are right, there is a file association that calls the program that runs this type of DLL, it is RunDLL.exe (not control.exe, this program just opens a window and lists all the CPL files, nothing more).

Casper

zooba

Quote from: Casper on June 25, 2006, 01:12:23 PM
zooba,
You have missed the entrire point of the discussion.

Strange, I thought I had followed it perfectly.

Quote from: Casper on June 25, 2006, 01:12:23 PM
The point Hutch is making is that there must be a call statement in the DLL

Quote from: hutch-- on June 23, 2006, 12:53:50 PM
you can load a DLL in a couple of ways ... you then must call the procedure you require.

Nope, Hutch's point was definitely that you load it first and then call the procedure.

In fact, I'll almost go so far as to say you've missed the point:

Quote from: Casper on June 22, 2006, 03:33:02 PM
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


The 'call Main' is the exact line that isn't required. There are few (if any) legitimate purposes for executing large amounts of code while attaching to a process. More likely you'd initialise the minimum number of variables required and export an initialisation function to allow the calling application to run it when it wants to.

This is exactly what rags pointed out to you, which you apparently ignored and then posted code proving yourself wrong. There is only one 'type' of DLL, but there are infinite amount of uses and a large number of standard interfaces (such as COM, ActiveX, control panels, Quick Editor plugins, etc.).

The defining characteristic of a dynamic-link-library, is that it is useless on its own. Without a process to load it, call the functions exported from it, and close it, it can do nothing.

hutch--

Casper,

The code you posted is a perfectly normal DLL, it has the entry point which is only called by the OS and in that proc it sets the instance handle. The following procedure for the Control Panel is not called by the Entry Point procedure but by another application. If you have a look in the masm32 example code there is a smal demo for calling control panel apps called RUNCPL that uses this code to start a CPL DLL.


        STRING RunDLL,"rundll32.exe shell32.dll,Control_RunDLL "
        mov BYTE PTR path[0], 0
        invoke szMultiCat,2,ADDR path,ADDR RunDLL,ADDR buffer
        invoke WinExec,ADDR path,SW_SHOW
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

donkey

Never liked WinExec, this is the RunCPL routine from WinExplorer...

RunCPL FRAME pszCPLFile
LOCAL CmdLine[MAX_PATH] :B
LOCAL sui :STARTUPINFO
LOCAL pi :PROCESS_INFORMATION

CInvoke(wsprintf,offset CmdLine,'rundll32 shell32,Control_RunDLL "%s"',[pszCPLFile])

mov D[sui.cb],SIZEOF STARTUPINFO
invoke GetStartupInfo,OFFSET sui
invoke CreateProcess,NULL,OFFSET CmdLine,NULL,NULL,\
TRUE,NULL,NULL,NULL,OFFSET sui,OFFSET pi
test eax,eax
jz >.ERROR
invoke CloseHandle,[pi.hProcess]
invoke CloseHandle,[pi.hThread]

xor eax,eax
RET

.ERROR
xor eax,eax
dec eax
ret
ENDF


Basically the same thing but using CreateProcess instead.

Donkey
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

Casper

Everybody,
Thank you for setting me straight.  I struggle with English at times but I do okay.  Donkey I never saw anything quite like that type of replacement for winexec.

Casper

donkey

Hi Casper,

You should never use WinExec, it is flawed and a security risk. If you mistakenly decide to use it make sure you always encorporate the path in quotes as specified by Microsoft on MSDN. CreateProcess is the only function you should be using to launch a process, WinExec is deprecated and has a security hole due to the command line parser it uses.

Quote from: MSDN WinExecSecurity Remarks

The executable name is treated as the first white space-delimited string in lpCmdLine. If the executable or path name has a space in it, there is a risk that a different executable could be run because of the way the function parses spaces. The following example is dangerous because the function will attempt to run "Program.exe", if it exists, instead of "MyApp.exe".

WinExec("C:\\Program Files\\MyApp", ...)

If a malicious user were to create an application called "Program.exe" on a system, any program that incorrectly calls WinExec using the Program Files directory will run this application instead of the intended application.

To avoid this problem, use CreateProcess rather than WinExec.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

zooba

CreateProcess uses the same parser for the lpCommandLine argument if, as in your example above, lpApplicationName is blank (of course, your example doesn't give a full path so it's fine, but so is Hutch's):

Quote from: MSDN CreateProcessThe lpApplicationName parameter can be NULL. In that case, the module name must be the first white space-delimited token in the lpCommandLine string. If you are using a long file name that contains a space, use quoted strings to indicate where the file name ends and the arguments begin; otherwise, the file name is ambiguous. For example, consider the string "c:\program files\sub dir\program name". This string can be interpreted in a number of ways. The system tries to interpret the possibilities in the following order:

c:\program.exe files\sub dir\program name
c:\program files\sub.exe dir\program name
c:\program files\sub dir\program.exe name
c:\program files\sub dir\program name.exe

Cheers,

Zooba :U

hutch--

An interesting enough example, I can duplicate Edgar's example with WinExec so that it runs the wrong file but I can also duplicate it with CreateProcess() if the 2nd argument contains the file name instead of the first.


    fn CreateProcess,"long name\call me.exe",NULL, \    ; works correctly
                     NULL,NULL,NULL,NULL,NULL,NULL, \
                         ADDR st_info, \
                         ADDR pr_info


    fn CreateProcess,NULL,"long name\call me.exe", \    ; fails like WinExec
                     NULL,NULL,NULL,NULL,NULL,NULL, \
                         ADDR st_info, \
                         ADDR pr_info


Both WinExec() and CreateProcess() fail when they are passed a command line so I would tend to see the problem as an OS defect that needs to be fixed by the vendor and if you are worried about this potential problem, use one form of CreateProcess() where you seperate the file name from the command tail as a work around.

Edgar's suggestion fixes the problem in both CreateProcess() and WinExec().


main proc

    LOCAL st_info:STARTUPINFO
    LOCAL pr_info:PROCESS_INFORMATION

    .data
      fname db 34,"long name\call me.exe",34,0
    .code

    fn WinExec,OFFSET fname,1

  ; ---------------------
  ; zero fill STARTUPINFO
  ; ---------------------
    mov ecx, 17                 ; 68 bytes SIZEOF STARTUPINFO
    lea edx, st_info
    xor eax, eax
  @@:
    mov [edx], eax
    add edx, 4
    sub ecx, 1
    jnz @B

    mov st_info.cb, 68          ; set the structure size member

    fn CreateProcess,NULL,OFFSET fname, \
                     NULL,NULL,NULL,NULL,NULL,NULL, \
                     ADDR st_info, ADDR pr_info

    invoke CloseHandle, pr_info.hThread
    invoke CloseHandle, pr_info.hProcess

    ret

main endp
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

hutch--

Here is a simple proc that should be as easy to use as WinExec().


; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

AppExec proc pcline:DWORD

    LOCAL pbuf  :DWORD
    LOCAL buffer[260]:BYTE
    LOCAL st_info:STARTUPINFO
    LOCAL pr_info:PROCESS_INFORMATION

    mov pbuf, ptr$(buffer)
    mov pbuf, cat$(pbuf,chr$(34),pcline,chr$(34))

  ; ---------------------
  ; zero fill STARTUPINFO
  ; ---------------------
    mov ecx, 17                 ; 68 bytes SIZEOF STARTUPINFO
    lea edx, st_info
    xor eax, eax
  @@:
    mov [edx], eax
    add edx, 4
    sub ecx, 1
    jnz @B

    mov st_info.cb, 68          ; set the structure size member

    fn CreateProcess,NULL,pbuf,NULL,NULL,NULL,NULL,NULL,NULL, \
                     ADDR st_info, ADDR pr_info

    invoke CloseHandle, pr_info.hThread
    invoke CloseHandle, pr_info.hProcess

    ret

AppExec endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

zooba

I imagine that's exactly what WinExec does now (if not forever) anyway. I don't see why they'd duplicate code.

The 'work-around' of passing the module name and the parameters separately is actively encouraged by Microsoft, and the potential problems with not doing so are well documented. If programmers choose to ignore it, it's their own fault.

Having said that, I think someone posted a while back that IE apparently doesn't separate the program for 'View Source' from the file...  :bdg

Cheers,

Zooba :U

Casper

askm,
I am many sorry to cause this deviation but we both are learning something as a result, right.

Hutch,
I am adding the last version into a project so I will nmot loose it.  This may be my learning showing but I have one more question and then I will shut up.  pcline is a pointer to the program to run, I think.  I think it could point to a string that might contain "c:\windows\notepad.exe"  So I think I know that one but in the following:
    mov pbuf, ptr$(buffer)
    mov pbuf, cat$(pbuf,chr$(34),pcline,chr$(34))


What does buffer contain?
Casper

hutch--

Casper,

The buffer is just a piece of memory to add the other strings to. The "ptr$" macro zeros it and the "cat$" macro appends string data to the blanked buffer one piece at a time.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Casper

Oh, Now I understand how it works.  It is very nice and I thank you for it.  Now, I will play.

Casper