Jump to content

How To Use "Open" And "Save As" (Win32 API) ?

- - - - -

  • Please log in to reply
12 replies to this topic

#1
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,252 posts
  • Location:C:\Countries\US
I'm trying to make this program that would ask the user what file they want to copy and whither they want to copy it.

I already put most of the code together, but I just don't know what Win32 API functions to use for the "Open" and "Save As" dialogs.

Here's the code so far, in case that's needed:
.386 

.model flat, stdcall 

option casemap:none 

include \RS\include\ifiles.inc                ;; All the includes, such as windows.inc, kernel32.inc, ...  

.data 

.data? 

filename1                               DB  512  dup (?) 

filename2                               DB  512  dup (?) 

buffer                                  DB  8172 dup (?) 

nBytes                                  DWORD ? 

.code 

start: 


call main 


xor eax, eax 

ret 


main proc 

	enter 8, 0 

	;; [ebp-4]= hFile1, [ebp-8]= hFile2 

	

	;; ... get filename1 and filename2 ...  

	

	push dword ptr 0 

	push dword ptr space(SIZEOF OFSTRUCT) 

	push dword ptr offset filename1 

	call OpenFile 

	mov dword ptr [ebp-4], eax 

	

	push dword ptr 1 or 1000h 

	push dword ptr space(SIZEOF OFSTRUCT) 

	push dword ptr offset filename2 

	call OpenFile 

	mov dword ptr [ebp-8], eax 

	

	lp1: 

		push dword ptr 0 

		push dword ptr offset nBytes 

		push dword ptr 4096 

		push dword ptr offset buffer 

		push dword ptr [ebp-4] 

		call ReadFile 

		cmp dword ptr [nBytes], 0 

		jz lp1s 

		

		push dword ptr 0 

		push dword ptr integer() 

		push dword ptr [nBytes] 

		push dword ptr offset buffer 

		push dword ptr [ebp-8] 

		call WriteFile 

		

		jmp lp1 

	lp1s: 

	

	push dword ptr [ebp-8] 

	call CloseHandle 

	

	push dword ptr [ebp-4] 

	call CloseHandle 

	

	leave 

	ret 0 

main endp 


end start 


#2
_dm

_dm

    Newbie

  • Members
  • Pip
  • 1 posts
GetOpenFileName: GetOpenFileName Function (Windows)
GetSaveFileName: GetSaveFileName Function (Windows)

#3
Kuto

Kuto

    Learning Programmer

  • Members
  • PipPipPip
  • 49 posts
GetOpenFileName for open dialog and GetSaveFileName for save dialog. An example function in C
void OpenFileDialog(char* filename)
{
    OPENFILENAME ofn    = {sizeof(ofn)};
    
    ofn.hInstance   = NULL;
    ofn.lpstrFilter = "All\0*.*\0";
    ofn.lpstrFile   = filename;
    ofn.nMaxFile    = MAX_PATH;
    GetOpenFileName(&ofn);
}


#4
Gunner

Gunner

    Learning Programmer

  • Members
  • PipPipPip
  • 45 posts
Something like this?
.data?
; This can be used for getting the file to open or save to
ofn                    OPENFILENAME <?>
lpSomeFile            BYTE    MAX_PATH + 1 dup (?)

.data
szDlgTitle            BYTE    "Open Some File", 0
szDlgFilter            BYTE    "Some Files(*.txt); (*.csv) (*.log)", 0, "*.txt; *.csv; *.log", 0, 0

.code
    ; Clear OpenFileName struct
    invoke    RtlZeroMemory, offset ofn, sizeof OPENFILENAME
    
    mov        ofn.lStructSize, sizeof OPENFILENAME
    push    hWin
    pop        ofn.hwndOwner
    mov        ofn.lpstrFilter, offset szDlgFilter
    mov        ofn.lpstrTitle, offset szDlgTitle
    mov        ofn.Flags, OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST
    mov        ofn.lpstrFile, offset lpSomeFile
    mov        ofn.nMaxFile, sizeof lpSomeFile
    invoke    GetOpenFileName, offset ofn
    test    eax, eax
    jz        Canceled
    
    ; Do something with the returned file here
 invoke    MessageBox, NULL, offset lpSomeFile, NULL, NULL
; call your open file function?  Or use CreateFile to open the file and get a handle

Canceled:
    ; ret from your function maybe

And then there is GetSaveFileName

One MUST have tool for any Win32 ASM programmer is the Windows SDK (I think it is called something else now) You can download it or get it on CD from MS (I did both :rolleyes:)

#5
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,252 posts
  • Location:C:\Countries\US
I'll try it and check back later.

#6
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
FYI be careful with the calling conventions. WinAPI calls use a different convention from the standard C library, so you might experience some weird issues.
sudo rm -rf /

#7
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,252 posts
  • Location:C:\Countries\US

Quote

FYI be careful with the calling conventions. WinAPI calls use a different convention from the standard C library, so you might experience some weird issues.
Is this the calling convention you're talking about?:
	push dword ptr 0 

	push dword ptr space(SIZEOF OFSTRUCT) 

	push dword ptr offset filename1 

	call OpenFile 

	mov dword ptr [ebp-4], eax 


#8
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
Eh...not sure what you're showing me there. The difference is that with cdecl the caller cleans up the stack, but with stdcall (WinAPI) the callee cleans up the stack, usually by providing a number with the ret instruction.
sudo rm -rf /

#9
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,252 posts
  • Location:C:\Countries\US
Yeah, that's what I'm used to.

push dword 65 

call some_function 


xor eax, eax 

ret 


some_function: 

enter 0, 0 


mov eax, dword [ebp+8] 


leave 

ret 4 


Thanks anyway.

#10
Gunner

Gunner

    Learning Programmer

  • Members
  • PipPipPip
  • 45 posts
Yes, in a way... your procs are your procs, if you want to use FASTCALL go ahead, but for the most part most functions you will write are STDCALL, where you know how many params were pushed on the stack so you will be able to ret 4 * n. *MOST* Win API calls are STDCALL so you should have no problems pushing and calling, but some use the C calling convention where you have to add to esp after the call, like for example wsprintf in user32.lib. That function has NO way of knowing how many optional params were pushed on the stack, so after the call you will have to add to esp to get the stack right.

#11
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
GCC--and I'd imagine other compilers as well--don't manipulate ESP after every function call. Instead, they subtract enough space to pass all arguments at the beginning of the function, then add it back later:
foo:
    push    ebp
    mov     ebp, esp
    sub     esp, 128
    
    mov     DWORD [esp], 0
    mov     DWORD [esp + 4], 1
    ...
    mov     DWORD [esp + 124], 32
    call    lotsa_arguments
    
    ...
    
    mov     DWORD [esp], 0xf00d
    call    one_argument_func
    
    ...
    add     esp, 128
    pop     ebp
    ret

You can get away with a lot this way.
sudo rm -rf /

#12
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,252 posts
  • Location:C:\Countries\US
Thanks guys.

I have this code, now:
.386 

.model flat, stdcall 

option casemap:none 

include \RS\include\ifiles.inc                ;; All the includes, such as windows.inc, kernel32.inc, ...  

.data 

ApplicationName                         db "TypeFile", 0 

.data? 

filename1                               DB  512  dup (?) 

filename2                               DB  512  dup (?) 

buffer                                  DB  8172 dup (?) 

nBytes                                  DWORD ? 


openfilename                            DB  SIZEOF OPENFILENAME dup (?) 

.code 

start: 


call main 


xor eax, eax 

ret 


main proc 

	enter 8, 0 

	;; [ebp-4]= hFile1, [ebp-8]= hFile2 

	

	mov ebx, offset openfilename 

	mov dword ptr [ebx+00], SIZEOF openfilename 

	mov dword ptr [ebx+12], string("All Files", 0, "*.*", 0) 

	mov dword ptr [ebx+28], offset filename1 

	mov dword ptr [ebx+32], SIZEOF filename1 

	mov dword ptr [ebx+44], 0                       ;; Initial directory. 

	

	push ebx 

	call GetOpenFileName 

	

	mov ebx, offset openfilename 

	mov dword ptr [ebx+00], SIZEOF openfilename 

	mov dword ptr [ebx+12], string("All Files", 0, "*.*", 0) 

	mov dword ptr [ebx+28], offset filename2 

	mov dword ptr [ebx+32], SIZEOF filename2 

	mov dword ptr [ebx+44], 0                       ;; Initial directory. 

	

	push ebx 

	call GetSaveFileName 

	

	push dword ptr 0 

	push dword ptr space(SIZEOF OFSTRUCT) 

	push dword ptr offset filename1 

	call OpenFile 

	mov dword ptr [ebp-4], eax 

	

	push dword ptr offset filename2 

	call WrFile 

	mov dword ptr [ebp-8], eax 

	

	lp1: 

		push dword ptr 0 

		push dword ptr offset nBytes 

		push dword ptr 4096 

		push dword ptr offset buffer 

		push dword ptr [ebp-4] 

		call ReadFile 

		cmp eax, 0 

		jz lp1e 

		cmp dword ptr [nBytes], 0 

		jz lp1s 

		

		push dword ptr 0 

		push dword ptr integer() 

		push dword ptr [nBytes] 

		push dword ptr offset buffer 

		push dword ptr [ebp-8] 

		call WriteFile 

		

		jmp lp1 

	lp1e: 

		push dword ptr 0 

		push dword ptr offset ApplicationName 

		push dword ptr string("An error occurred while reading input file. ") 

		push dword ptr 0 

		call MessageBoxA 

		jmp lp1s 

	lp1s: 

	

	push dword ptr [ebp-8] 

	call CloseHandle 

	

	push dword ptr [ebp-4] 

	call CloseHandle 

	

	push dword ptr 0 

	call ExitProcess 

	

	leave 

	ret 0 

main endp 


WrFile proc 

	enter 0, 0 

	push ebx 

	

	push dword ptr 0 

	push dword ptr 128       ;; File attribute normal. 

	push dword ptr 2         ;; New file, always. 

	push dword ptr 0 

	push dword ptr 7         ;; File share. 

	push dword ptr GENERIC_READ or GENERIC_WRITE 

	push dword ptr [ebp+8] 

	call CreateFile 

	

	pop ebx 

	leave 

	ret 4 

WrFile endp 


end start 

For some reason it wouldn't exit after doing the job, so I had to insert an ExitProcess() function call. But it works.




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users