Getting confused with FindFirstFile and FindNextFile

Started by white scorpion, May 05, 2008, 09:38:04 PM

Previous topic - Next topic

white scorpion

Hi all,

I'm trying to add a functionality to an existing program of mine so that it can delete folders, sub files and sub folders with their files.
For this I take it FindFirstFile and FindNextFile would be the best solution.
However, I'm a bit confused  :dazzled: about the best solution for listing sub folders and their files.

Let's say I have the following folder structure:

C:\temp
C:\temp\test.txt
C:\temp\folder
C:\temp\folder\test1.txt
C:\temp\folder\folder2
C:\temp\folder\folder2\test2.txt


Since I do not know in advance how many sub folders will exist in the root folder and how many sub folder each sub folder has, etc.
How can I write a program which would list all of them, one by one, file by file, without having to create a huge amount of handles?

I have the following code already, which lists the files and folders from the root folder (C:\temp) perfectly, but after that I assume I would have to test each found file to see if it's a folder and if so, do the same thing all over again but with a different handle since I need to keep the original handle of the root folder to continue after I've finished with the subfolder.

Maybe I'm overlooking something, but I can't seem to get this fixed.
Here's the code:

.686
.model flat,stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc

includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib

.DATA
mytestpath db 'C:\temp\*',0
nofile db 'Error: Invalid path specified.',0
myTitle db 'Folder Test',0
dot db '.',0
ddot db '..',0

.DATA?
mybuf    db 512 dup (?)
wfd WIN32_FIND_DATA <>
hFind dd ?

.CODE
start:

invoke FindFirstFile, addr mytestpath, addr wfd
.IF eax==INVALID_HANDLE_VALUE
invoke MessageBoxA,NULL,addr nofile,addr myTitle,MB_ICONERROR
invoke ExitProcess,0
.ENDIF
mov hFind,eax
invoke lstrcmp,addr wfd.cFileName,addr dot
.IF eax!=0
invoke lstrcmp,addr wfd.cFileName,addr ddot
.IF eax!=0
invoke MessageBoxA,NULL,addr wfd.cFileName,addr myTitle,MB_OK
.ENDIF
.ENDIF

@@:
invoke FindNextFile,hFind,addr wfd
.IF eax!=0
invoke lstrcmp,addr wfd.cFileName,addr dot
.IF eax!=0
invoke lstrcmp,addr wfd.cFileName,addr ddot
.IF eax!=0
invoke MessageBoxA,NULL,addr wfd.cFileName,addr myTitle,MB_OK
.ENDIF
.ENDIF
jmp @B
.ENDIF

invoke FindClose,hFind
invoke ExitProcess,0
end start


The only thing I can think of is to create a recursive function. would this be the best solution?

hutch--

Normally you use a recursive function to climb up and down directory trees, what may be the problem is to get it into the order you require as this method will display directories in the order they were created on disk.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

white scorpion

Well, the order doesn't really matter, it was just an example.
The program securely deletes files, in what order, who cares :p

So a recursive function would be the best solution?

hutch--

Basically yes, where you need to do some more woork is if any of the files are protected and must have their file attributes changed to archive first before you can delete them.

The attached file is my last play with this type of code. be careful and test it on a partition the has nothing useful on it as in its development where i was testing on a tail end partition, I managed to trash everything on the partition. I just forget where I left it as its been a few years since i have seen it.

[attachment deleted by admin]
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Tedd

If your only aim is to remove a folder and all of its contents, you can simply use the SHFileOperation function set to FO_DELETE
http://msdn.microsoft.com/en-us/library/bb762164.aspx
No snowflake in an avalanche feels responsible.

white scorpion

Thanks Hutch, I'll give it a close look ;)

@Tedd, it's not that easy. What I want is to be sure the files cannot be restored anymore, this means that we'll have to overwrite it several times manually.

I wrote a program with that functionality, works great, but only works for 1 file at the time.
So I want to add folders to it as well, hence the required function ;)

codewarp

The recursive function that Hutch speaks of is very convenient (no, actually it's perfect), because if lets you easily delete your directory trees from bottom up.  You have to delete from from bottom up, because you can't delete a directory until it is completely empty.

Grincheux

@Tedd, it's not that easy. What I want is to be sure the files cannot be restored anymore, this means that we'll have to overwrite it several times manually.

I thought that many softwares could delete file without the possibility of restore until I used the OnTrack software. Even with a good software like yours, I think that the file will be restored unless you fill all the disk...

Good dream...
Kenavo

Grincheux
_____________________________________________________
http://www.phrio.biz

Jimg

The three programs included print out the name of all files in the current folder
         and all sub-folders.

r1:   Uses recursion, changes folders as it works, is the smallest code, slowest,
         and uses most memory.

r2:   Uses recursion, does not change folders while it works, is medium size and speed.

r3:   Does not use recursion or change folders, is the largest and fastest, and
          uses the least amount of memory while working.


And finally, a useful program.

r4:   A routine written so you can call it repeatedly to get the next file name whenever
          you need it.  The example program just prints out the file name, but you could do
          anything you wanted with the return.

[attachment deleted by admin]

Grincheux

Here http://www.idcat39.com/download/Bin/DirsAndFiles.exe is a program example for getting files list.
It uses a recursive algo.
This program comes with my own asm library but the research function is into a small file named "Search Files.asm".
The program generates two files : The first is used to store the directories found with an index. The second file is used to store the files names found. There is an index per file and an index on the directory into which there were found.
This program makes part of a program I have just began so it does not make a lot of things.
I have created a log window that you can use to store some actions for debugging.

Good luck
Kenavo

Grincheux
_____________________________________________________
http://www.phrio.biz

Jimg

Now I remember why I stopped working on those routines-

This is simple, small, and really couldn't be any faster since most all of the execution time is taken up with actual disk access.

; from jimg
include \masm32\include\masm32rt.inc
.code
program:
.data
  cmd2  db 'cmd /c dir "f:\*.asm" /s/w/b/a-d > '  ; the file specification wanted
  dest2 db "r:allfile.txt",0

  cmd3  db 'cmd /c dir "f:\*.*" /s/w/b/ad > '     ; to get all the folder names
  dest3 db "r:allfold.txt",0

.code
    invoke wshell,addr cmd2 ; get all the files
    invoke wshell,addr cmd3 ; get all the folders
   
; that's it.  really simple.   


; example of reading the results
.data
  aline dd 170 dup (0)
  spos dd 0
  answ dd 0
  alen dd 0
  lcnt dd 0
.code
    invoke read_disk_file,addr dest2,addr answ,addr alen
    .repeat
        invoke readline,answ,addr aline,spos
        mov spos,eax
        inc lcnt
    .until eax==0
    invoke GlobalFree,answ
    invoke wsprintf,addr aline,SADD("lines read=%li"),lcnt
    invoke MessageBox,0,addr aline,0,0
    invoke ExitProcess,eax
end program