flat assembler
Message board for the users of flat assembler.

Index > Windows > WinInet functions example

Author
Thread Post new topic Reply to topic
Picnic



Joined: 05 May 2007
Posts: 1396
Location: Piraeus, Greece
Picnic 09 Jul 2009, 22:17
Hi all,
I'm reading about WinInet functions, below is a small sample i wrote on fasm demonstrating few basic functions, hope it's useful.

Code:
        ; WinInet functions example.
        ; The following sample code establish a connection to an FTP server.
        ; It controls how long to wait while connecting to the FTP server in WinInet.
        ; It downloads a file from FTP server to local disk and displays the download progress on Console title.
        ; FTP account username and password required.
        
        ; Written by thimis
        ; Fasm v1.69.02
        ; Tested on Windows XP

        format PE CONSOLE 4.0
        entry main

        include 'include\win32ax.inc'

        INFINITE = -1
        INTERNET_SERVICE_FTP = 1
        INTERNET_DEFAULT_FTP_PORT = 21
        INTERNET_OPEN_TYPE_DIRECT = 1
        FTP_TRANSFER_TYPE_BINARY = 2
        INTERNET_FLAG_TRANSFER_BINARY = 2
        INTERNET_FLAG_RELOAD = 0x80000000
        INTERNET_FLAG_DONT_CACHE = 0x4000000
        CONTENT_LENGTH = 4096

.data
        szHost TCHAR '',0                   ; xxx.xxx.xxx.xxx
        szUser TCHAR '',0                   ; username
        szPass TCHAR '',0                   ; password
        szRemoteFile TCHAR '',0             ; /music/test.mp3
        szLocalFile TCHAR '',0              ; c:\test.mp3

        lpExitCode dd 0
        lpBytesRead dd 0
        lpCharsWritten dd 0

        dwTimeout dd 0
        dwThreadID dd 0
        dwTotalBytes dd 0

        hStdOut dd 0
        hConnect dd 0
        hOpen dd 0
        hThread dd 0
        hFile dd 0
        hHeap dd 0
        hMem dd 0
        hRequest dd 0

        Buffer db 256 dup ?

.code
main:
        ; ///Returns a handle for the standard output
        invoke GetStdHandle, STD_OUTPUT_HANDLE
        .if eax = -1
            stdcall LastError, <'GetStdHandle() failed. Error code %d'>
            jmp Exit
        .endif

        mov [hStdOut], eax
        

        ;  ///Obtains a handle to the heap of the calling process
        invoke GetProcessHeap
        .if ~eax
            stdcall LastError, <'GetProcessHeap() failed. Error code %d'>
            jmp Exit
        .endif

        mov [hHeap], eax
        

        ; ///Allocates a block of memory from a heap
        invoke HeapAlloc, [hHeap], HEAP_ZERO_MEMORY, CONTENT_LENGTH+1
        .if ~eax
            stdcall LastError, <'HeapAlloc() failed. Error code %d'>
            jmp Exit
        .endif

        mov [hMem], eax
        

        ; ///Initializes use of the WinINet functions
        invoke InternetOpen, NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, 0, 0
        .if ~eax
            stdcall LastError, <'InternetOpen() failed. Error code %d'>
            jmp Exit
        .endif

        mov [hOpen], eax
        

        ; ///Create a connection thread
        invoke CreateThread, NULL, 0, Thread, 0, 0, 0
        mov [hThread], eax

        ; ///Wait for the call to InternetConnect in thread function to complete
        mov [dwTimeout], 10000
        invoke WaitForSingleObject, [hThread], [dwTimeout]
        .if eax = WAIT_TIMEOUT
            stdcall Print, <'Can not connect to FTP server.',13,10>
            .if [hOpen]
                invoke InternetCloseHandle, [hOpen]
                mov [hOpen], 0
            .endif
            ; Wait until the thread exits
            invoke WaitForSingleObject, [hThread], INFINITE
            stdcall Print, <'Thread has exited.',13,10>
            jmp Exit
        .endif

        ; ///The state of the specified thread is signaled
        invoke GetExitCodeThread, [hThread], lpExitCode
        .if ~eax
            stdcall LastError, <'GetExitCodeThread() failed. Error code %d'>
            jmp Exit
        .endif

        invoke CloseHandle, [hThread]

        .if [lpExitCode]
            ; ///Thread function failed
            jmp Exit
        .endif

        
        ; ///Initiates access to a remote file on an FTP server for reading or writing
         invoke FtpOpenFile, [hConnect], szRemoteFile, GENERIC_READ,\
                   INTERNET_FLAG_TRANSFER_BINARY+INTERNET_FLAG_DONT_CACHE+INTERNET_FLAG_RELOAD, 0
        .if ~eax
            stdcall LastError, <'FtpOpenFile() failed. Error code %d'>
            jmp Exit
        .endif

        mov [hRequest], eax
        

        ; ///Creates a new file on disk. The function overwrites the file if it exists
        invoke CreateFile, szLocalFile, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0
        .if eax = -1
            stdcall LastError, <'CreateFile() failed. Error code %d'>
            jmp Exit
        .endif

        mov [hFile], eax
        

        stdcall Print, <'Downloading file from FTP server...',13,10>

        ; ///Read from file on the server in a loop chunks of 4Kb each
        .repeat
            invoke InternetReadFile, [hRequest], [hMem], CONTENT_LENGTH, lpBytesRead
            .if eax
                ; ///Write the memory buffer to file on disk
                invoke WriteFile, [hFile], [hMem], [lpBytesRead], lpCharsWritten, 0
                mov ecx, [lpCharsWritten]
                add [dwTotalBytes], ecx
                ; /// Sets the title bar string for the current Console
                invoke wsprintf, Buffer, <'Downloaded %d bytes so far..'>, [dwTotalBytes]
                invoke SetConsoleTitle, Buffer
            .endif
        .until ~[lpBytesRead]

        
        ; /// File download completed
        cinvoke wsprintf, Buffer, <'Download completed. Total %d bytes.',13,10>, [dwTotalBytes]
        stdcall Print, Buffer


        
; ///Release allocated memory, close open handles and exit program
Exit:
        .if [hFile]
            invoke CloseHandle, [hFile]
        .endif
        .if [hMem]
            invoke HeapFree, [hHeap], 0, [hMem]
        .endif
        .if [hRequest]
             invoke InternetCloseHandle, [hRequest]
        .endif
        .if [hOpen]
            invoke InternetCloseHandle, [hOpen]
        .endif
        .if [hConnect]
            invoke InternetCloseHandle, [hConnect]
        .endif

        invoke ExitProcess, 0



proc  Thread
        stdcall Print, <'Trying to establish connection...',13,10>

        ; ///Call InternetConnect to establish a FTP session
        invoke InternetConnect, [hOpen], szHost, INTERNET_DEFAULT_FTP_PORT,\
                  szUser, szPass, INTERNET_SERVICE_FTP, 0, 0
        .if ~eax
            stdcall LastError, <'InternetConnect() failed. Error code %d'>
            mov eax, 1
        .else
            mov [hConnect], eax
            stdcall Print, <'Connection established to FTP server.',13,10>
            xor eax, eax
        .endif
        ret
endp



; ///Prints a character string to Console
proc  Print lpBuffer
        cinvoke wsprintf, Buffer, [lpBuffer]
        invoke WriteConsole, [hStdOut], Buffer, eax, lpCharsWritten, 0
        .if ~eax
            stdcall LastError, <'WriteConsole() failed. Error code %d'>
            jmp Exit
        .endif
        ret
endp



; ///Displays last-error info & code value
proc  LastError lpBuffer
        invoke GetLastError
        cinvoke wsprintf, Buffer, [lpBuffer], eax
        invoke MessageBox, HWND_DESKTOP, Buffer, 0, MB_OK+MB_ICONERROR
        ret
endp



data import

        library kernel32,'KERNEL32.DLL',\
                 user32,'USER32.DLL',\
                 wininet,'WININET.DLL'

        include 'include\api\kernel32.inc'
        include 'include\api\user32.inc'
        include 'include\api\wininet.inc'

end data
    


Description:
Filesize: 19.1 KB
Viewed: 5394 Time(s)

ex4.jpg


Post 09 Jul 2009, 22:17
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4060
Location: vpcmpistri
bitRAKE 09 Jul 2009, 23:53
Maybe I can adapt this to mirror some folders at ftp://download.intel.com
It is nice to have the latest manuals here locally.
Post 09 Jul 2009, 23:53
View user's profile Send private message Visit poster's website Reply with quote
windwakr



Joined: 30 Jun 2004
Posts: 827
windwakr 10 Jul 2009, 01:19
Nice program

bitRAKE, where are the manuals located on the ftp?

EDIT: Thanks.


Last edited by windwakr on 10 Jul 2009, 04:04; edited 1 time in total
Post 10 Jul 2009, 01:19
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4060
Location: vpcmpistri
bitRAKE 10 Jul 2009, 04:01
\design\processor\manual\
Post 10 Jul 2009, 04:01
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4060
Location: vpcmpistri
bitRAKE 10 Jul 2009, 04:04
\design\processor\manual\

*Use "dir.txt" in the root to find other files - it is updated daily.
Post 10 Jul 2009, 04:04
View user's profile Send private message Visit poster's website Reply with quote
Picnic



Joined: 05 May 2007
Posts: 1396
Location: Piraeus, Greece
Picnic 11 Jul 2009, 21:52
Hi guys,

I just noticed that invoke has to be replaced by cinvoke
I'm surprised it don't crash.
Code:
; /// Sets the title bar string for the current Console
invoke wsprintf, Buffer, <'Downloaded %d bytes so far..'>, [dwTotalBytes] 
    
Post 11 Jul 2009, 21:52
View user's profile Send private message Visit poster's website Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 11 Jul 2009, 22:39
Because for every 4 KB chunk you loose only 12 bytes of stack space. Perhaps you never tried with a long enough file.
Post 11 Jul 2009, 22:39
View user's profile Send private message Reply with quote
Picnic



Joined: 05 May 2007
Posts: 1396
Location: Piraeus, Greece
Picnic 11 Jul 2009, 23:32
Hi LocoDelAssembly,
I tested some mp3 files few mb each.
Post 11 Jul 2009, 23:32
View user's profile Send private message Visit poster's website Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 12 Jul 2009, 03:34
Less than 10 MB? That would be around 30 KB of stack memory usage, far less than the amount of stack used in http://board.flatassembler.net/topic.php?p=96788#96788 to make the program crash (~240 KB).

BTW, of course that the code must be fixed, I'm just pointing out why you may not perceive any crash despite the bug Razz
Post 12 Jul 2009, 03:34
View user's profile Send private message Reply with quote
DimonSoft



Joined: 03 Mar 2010
Posts: 1228
Location: Belarus
DimonSoft 12 Nov 2013, 18:07
Sorry for necroposting, but, Picnic, why do you need to create a connection thread if you wait for its completion anyway? It seems to be unnecessary, InternetConnect() can just be called in the main thread and nothing would have changed except that there would be no additional thread.
Post 12 Nov 2013, 18:07
View user's profile Send private message Visit poster's website 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-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.