In this tutorial, our main task is to display a message box with the names of all the items in the current directory, with each name having its own line. Windows provides us with API functions for tasks like that too.
Overview
- The Win32 API
- Example Program
The Win32 API
Let's quickly go over the Windows functions that we would use.
FindFirstFile
Used for starting a directory scan.
Parameters:
- The directory or path, and the filename (wildcards are allowed).
- A pointer to a WIN32_FIND_DATA structure that receives information about the first item (ie file, folder, etc.).
Return:
The return value is a find file handle for the current file search.
FindNextFile
Used for continuing a directory scan.
Parameters:
- The find file handle.
- A pointer to a WIN32_FIND_DATA structure; same idea as for FindFirstFile().
Return:
BOOL
If the function succeeds, the return value is non-zero. If the function failed, the return value is zero, and you can get extended error information by calling the GetLastError() Win32 API function.
FindClose
Just like with file handles, you have to close the find file handle when you're done using it. You do that using the FindClose() Win32 API function.
Parameters:
- The find file handle.
Return:
BOOL
If the function succeeds, the return value is non-zero (TRUE); the return value is zero (FALSE), otherwise.
GetLastError
You get the Windows system error code of the last error that occurred using this function.
Parameters:
none
Return:
The Windows system error code for the last error.
For more reference on these functions or structures, see references, at the end of this tutorial.
Example Program
We would define the dir_scan() function in this next example program.
The dir_scan() function searches for files, passing its first argument to the FindFirstFile() function as the first parameter.
For each item in the scan, it calls the callback function passed to it by the second argument.
It passes its third argument (optional parameter) to the callback function as the second argument, and it passes the pointer to its WIN32_FIND_DATA structure to the callback function as the first argument.
The Idea
In our case, we use the optional parameter for the pointer to the string that collects all the names of the items in the directory.
Every time our callback function is called, it appends the current item's filename to the string pointed to by our optional parameter.
That way, we can just display a message box, after calling the dir_scan() function, with our string that's for filenames.
The Code
;; Define the externs. extern FindFirstFileA extern FindNextFileA extern FindClose extern GetLastError extern MessageBoxA extern ExitProcess ;; Construct our symbol import table. import FindFirstFileA kernel32.dll import FindNextFileA kernel32.dll import FindClose kernel32.dll import GetLastError kernel32.dll import MessageBoxA user32.dll import ExitProcess kernel32.dll ;; The following goes into the code section of the program; use 32-bit code. section .text use32 ;; Start program execution at this point. ..start: ;; Call the main() function. call main ;; Exit, returning whatever main() returned. push eax call [ExitProcess] main: ;; [ebp-4096]= start of a string enter 4096, 0 ;; Initialize the string to "" (blank). mov byte [ebp-4096], 0 ;; Call the function that would scan through the directory listing. lea eax, [ebp-4096] push eax ;; This is the optional parameter for the callback function. ;; We use the address of our new string for this parameter. push dword our_callback_function ;; This is the address of the callback function; the callback ;; function is called for each item in the directory scan. push dword file_search_string ;; This is the path/string that is used for the search. call dir_scan ;; Now we display a message box with our new string. push dword 0 push dword the_title lea eax, [ebp-4096] push eax push dword 0 call [MessageBoxA] ;; Return 0. xor eax, eax leave ret ;; The callback function has to be in the dir_scan callback format. ;; dir_scan format: ;; parameters: ;; pFindData A pointer to a WIN32_FIND_DATA (ANSI version) structure that contains the information about the item (ie file). ;; optParam The optional parameter that was passed to dir_scan() as the third argument. ;; calling convention: standard our_callback_function: enter 4, 0 mov eax, dword [ebp+08] ;; The pointer to the WIN32_FIND_DATA structure. add eax, 44 ;; The offset of the filename part of the structure. push eax ;; The address of the filename (or directory name) string. push dword [ebp+12] ;; The optional parameter. call strcat ;; The job, here, is to append the filename to the string that's passed to us ;; with the optional parameter. ;; Set [ebp-4] to the "\r\n" string. mov byte [ebp-4], 13 mov byte [ebp-3], 10 mov word [ebp-2], 0 ;; Append that string to our other string that's passed by the optional parameter. lea eax, [ebp-4] push eax push dword [ebp+12] call strcat leave ret 8 ;; dir_scan() - Directory scan. ;; parameters: ;; pFileSearchString The directory or path, and the file name (wildcards are allowed). ;; pCallbackFunction The address of the (dir_scan) callback function. ;; optCallbackParam An optional parameter to pass to the callback function. dir_scan: ;; [ebp-318] = start of (ANSI version) WIN32_FIND_DATA structure. ;; [ebp-322] = hFindFile - find file handle. enter 318 + 4, 0 pusha lea eax, [ebp-318] push eax ;; The pointer to the WIN32_FIND_DATA structure. push dword [ebp+08] ;; The file search string. call [FindFirstFileA] mov dword [ebp-322], eax ;; Save the handle to the file search. .lp1: ;; Call the callback function. push dword [ebp+16] ;; The second argument is the optional parameter, passed to us earlier. lea eax, [ebp-318] push eax ;; The first argument is the pointer to the WIN32_FIND_DATA structure. call [ebp+12] ;; This function's second parameter is the address of the callback function. lea eax, [ebp-318] push eax ;; The address of the WIN32_FIND_DATA structure. push dword [ebp-322] ;; The handle to the file search. call [FindNextFileA] cmp eax, 0 ;; Error? jnz .lp1 ;; If no, continue the loop. call [GetLastError] ;; This function takes no parameters and returns the system error code of the last error. cmp eax, 18 ;; ERROR_NO_MORE_FILES = 18; means that there aren't any more files to scan. jz .lp1s ;; If no more files, break from the loop. ;; Otherwise, well, let's just close the hFindFile handle and return -1. push dword [ebp-322] call [FindClose] popa mov eax, -1 leave ret 12 .lp1s: ;; Close the find file handle. push dword [ebp-322] call [FindClose] popa xor eax, eax leave ret 12 %include "../inc/str.asm" ;; Include the file with the string function definitions. ;; The following is for the data section. section .data ;; The data definitions. the_title db "LS", 0 file_search_string db "*", 0
The Output

(Fullsize Screenshot)
"." means the current directory, and ".." means the parent directory.
References:
FindFirstFile Function (Windows)
FindNextFile Function (Windows)
FindClose Function (Windows)
GetLastError function (Windows)
WIN32_FIND_DATA Structure (Windows)
First Tutorial:
Intro To Win32 Assembly, Using NASM
Previous Tutorial:
Directory Handling - Making A New Directory
Next Tutorial:
Directory Handling - The Current Directory
















