News:

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

Getting filename

Started by white scorpion, February 28, 2005, 12:24:36 AM

Previous topic - Next topic

white scorpion

Hi all,

i'm trying to figure out an easy way to get the filename given to my program. eg:

in C you could do:

int main(int argc,char *argv[])
{
     printf("%s is the name of our file.",argv[0]);
     return 0;
}


now if i would try to use an API for this i would get the complete path including name. then i would have to remove the path at first to extract the filename.

here are the API's i have used:

GetCommandLine
GetModuleFileName
GetShortPathName

i have even tried:


include \masm32\include\masm32.inc
includelib \masm32\lib\masm32.lib

invoke GetCL,0,addr buffer



but this returns also the complete path :(

any ideas?

Thanks in advance!

donkey

If the function is returning the complete path then strip the filename out of it, it is fairly easy as it will always begin with the last \

invoke lstrlen, offset FileName
mov ecx,eax
mov edi, offset FileName
add edi, ecx
mov eax,"\"
std
repne scasb
cld
; The filename portion will begin at EDI+2
"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

Farabi

Use invoke GetCommandLine. Eax is the pointer to the path null terminated string.
Those who had universe knowledges can control the world by a micro processor.
http://www.wix.com/farabio/firstpage

"Etos siperi elegi"

n-w

I used:

invoke GetFullPathName
invoke GetModuleFileName, hInst, addr file, sizeof file
invoke lstrlen, addr path
add eax, offset file
-> addr of filename in eax

or something similar.

But I found no direct way to obtain the filename without path.

AeroASM

If you need a direct way, just make your own proc with the code to get the filename and put it in the masm32 library. Then you can just call it to get the filename.

MichaelW

Another, perhaps more familiar, method. But unless I needed only the filename without the extension, I would use donkey's method because this method requires more memory and more code.

; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .486                       ; create 32 bit code
    .model flat, stdcall       ; 32 bit memory model
    option casemap :none       ; case sensitive

    include \masm32\include\windows.inc
    include \masm32\include\masm32.inc
    include \masm32\include\kernel32.inc
    include \masm32\include\msvcrt.inc

    includelib \masm32\lib\masm32.lib
    includelib \masm32\lib\kernel32.lib
    includelib \masm32\lib\msvcrt.lib

    include \masm32\macros\macros.asm
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
      modpath    db MAX_PATH dup(0)
      moddrive   db 0,0,0
      moddir     db MAX_PATH dup(0)
      modfname   db MAX_PATH dup(0)
      modext     db MAX_PATH dup(0)
    .code
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    invoke GetModuleFileName,0,ADDR modpath,MAX_PATH
    print ADDR modpath
    print chr$(13,10)
    invoke _splitpath,ADDR modpath,
                      ADDR moddrive,
                      ADDR moddir,
                      ADDR modfname,
                      ADDR modext
    print ADDR moddrive
    print chr$(13,10)
    print ADDR moddir
    print chr$(13,10)
    invoke szCatStr,ADDR modfname,ADDR modext
    print ADDR modfname
    mov   eax,input(13,10,13,10,"Press enter to exit...")
    exit
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start

void _splitpath(
   const char *path,
   char *drive,
   char *dir,
   char *fname,
   char *ext
);

eschew obfuscation

white scorpion

i was afraid of that. i kindof hoped i could use a function which already exists since i'm working on several different machines and then i wouldn't have to make my own functions everytime i needed it.

but ok, i will do it with my own function then. Thanks for all responses :)


donkey

Well, unless you are changing architectures you can just put the function in a library and use it from that. I have a function that does this available in my files.lib library available from my website, it is both MASM and GoAsm compatible.
"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

white scorpion

well i've already written a PROC:


;***********************************************************
;Get FileName procedure, returns eax as offset
;***********************************************************
GetFileName PROC

LOCAL  FileName[2048] :BYTE

invoke GetModuleFileName,NULL,addr FileName,sizeof FileName

invoke lstrlen,addr FileName
mov ecx,eax
lea eax,FileName
add eax,ecx
next:
cmp byte ptr [eax],5Ch   ;first '\' from the back
jz contin
dec eax
jmp next
contin:
inc eax
ret
GetFileName ENDP
;***********************************************************


what do you think of it?


pbrennick

white scorpion,
There is a procedure in the masm32 library called NameFromPath:

This is what it does:

; #########################################################################

    .386
    .model flat, stdcall  ; 32 bit memory model
    option casemap :none  ; case sensitive

    .code

; ########################################################################

NameFromPath proc lpPath:DWORD,lpBuffer:DWORD

    push edi

    mov ecx, lpPath

  ; -------------------------------------------------------
  ; Scan path buffer for "\" and put each offset + 1 from
  ; ecx into edx. Offset of last occurrence of "\" + 1 will
  ; be in edx when loop exits on zero.
  ; -------------------------------------------------------

  @@:
    mov al, [ecx]
    inc ecx
    cmp al, 0           ; exit condition for 1st loop
    je @F
    cmp al, "\"         ; test for "\"
    jne @B
    mov edx, ecx        ; if "\" put ecx+1 offset in edx
    jmp @B
  @@:

    sub ecx, lpPath     ; length in ecx
    add ecx, edx        ; create exit condition

  ; ---------------------------
  ; copy file name to lpBuffer
  ; ---------------------------
    mov edi, lpBuffer
  @@:
    mov al, [edx]
    inc edx
    mov [edi], al
    inc edi
    cmp edx, ecx
    jne @B

    pop edi

    ret

NameFromPath endp

; #########################################################################

end


Why not use what already exists?
Paul

Mark Jones

 I've used this method of getting just a file's name:


.data
ofn OPENFILENAME<>      ; ofn = openfilename struct
buffer db 256 dup(0)    ; path & filename buffer
pFileName db 64 dup(0)  ; filename buffer

.code
    Invoke GetOpenFileName, Addr ofn        ; select a file
    .If Eax != 0                            ; if valid file is chosen
        Movzx EAX, WORD PTR ofn.nFileOffset ; pointer to where filename begins
        Mov ECX, OFFSET buffer              ; load the path into ecx
        Add ECX, EAX                        ; move to where the filename begins
        Mov DWORD PTR pFileName, ECX        ; save original filename pointer
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

white scorpion

QuoteWhy not use what already exists?
Paul
since i didn't knew of its existance... but to be honest i like mine better, since it is shorter and exactly what i need.

Faiseur

Quotenow if i would try to use an API for this i would get the complete path including name. then i would have to remove the path at first to extract the filename.

Hi white scorpion,

There is a simple solution with API  :-)


  invoke GetModuleFileName,NULL,addr FileName,sizeof FileName
  fn wsprintf, addr FileName, "%s", FUNC (PathFindFileName, addr FileName)


or eventualy:


  invoke GetModuleFileName,NULL,addr FileName,sizeof FileName
  fn wsprintf, addr FileName, "%s", FUNC (PathStripPath, addr FileName)



Include:

include shlwapi.inc
includelib shlwapi.lib

Regards,

faiseur
French asm Forum: http://www.asmforum.net/   Website: http://www.faiseur.net/

Relvinian

Faiseur,

Yep, using the Shell API calls makes things like getting the filename, extension or other information pretty easy.  ;-)

Relvinian

white scorpion

Thanks Faiseur, i will check it out, it sounds great!