This file find snippet is IMHO one of the most versatile around.

Features:
- Uses callbacks for easier file handling.
- Supports recursion so you can search your entire HD at one (but you don't have to use it).
- Returns the full path AND the bare filename to the callback, along with the WIN32_FIND_STRUCT so you have all the info you need.
- Can report directories before or after listing the files in them, or both (or not at all).
- Pretty damn fast too :)


Note that this is a beta release! I don't expect it to have (m)any serious bugs (coding errors), but maybe some "features" when handling weird search strings (design errors).
Posted on 2002-04-15 01:42:47 by Qweerdy
The RadASM project file with demo program and the inc file containing the proc.
Posted on 2002-04-15 01:43:40 by Qweerdy
Hi Qweerdy

Got a GPF on XP. :o

Never assume there aren't any bugs. :grin:

KetilO
Posted on 2002-04-15 01:58:37 by KetilO
I have Windows Xp too, KetilO... and I did test it pretty well.

I downloaded the zip and ran the test program... it just worked. I'll look into it, see if I missed anything obvious. Did you run the test program as-is or did you change the search string? If you did pls tell me what you changed it into.

Also, did it GPF immediately or after displaying one of the messageboxes?
Posted on 2002-04-15 02:06:38 by Qweerdy
Hi Qweerdy

I ran the test program as is. I have not had any chance to look at the code yet. I am planning to implement a file browser into RadASM's project tool. Your findings might be useful if it is ok for me to 'steal' the code.

KetilO
Posted on 2002-04-15 02:12:20 by KetilO
Your findings might be useful if it is ok for me to 'steal' the code.

Sure it's OK, that's why I'm posting it here :)

I've re-uploaded the zip, this version has a better demo program (error checking and less NULL parameters to the API's). I haven't modified the algorithm yet, since I couldn't spot any errors.

If it still GPF's, please tell me exactly what happened (ie were any msgboxes displayed before it crashed). Also, could you tell me if C:\dirtest.txt was created and if so could you post it here so I can see where the program crashed.

And of course I'm also still interested on other ppl's feedback.
Posted on 2002-04-15 02:24:59 by Qweerdy
Hi Qweerdy

Tested your second upload.
Same result: Instruction at 0x77F536F7 referenced memory at 0x00000000.
The dirtest.txt is created (323Kb), looks ok and probably contains all files.

KetilO
Posted on 2002-04-15 03:14:55 by KetilO
Athlon 1ghz WinME - Caused an error in Kernel32.dll after program completed saving the complete dirtest.txt

OllyDbg shows access violation when writing to 002A2E32
Posted on 2002-04-15 03:42:19 by gscundiff
mh this Looks very HUGE to me... just in case you're
interested in another ways... here's a small but slow
aproach... can scan for a single drive or ALL drives...



.DATA
FILE_MASK DB "*", 0
BACK DB "..", 0
TESTFILE DB "TEST.TXT", 0
BLA DB 13, 10

.DATA?
BUFFER DB 100 DUP ( ? )
W32FD WIN32_FIND_DATA < ? >
S_HANDLE DD ?
TESTHANDLE DD ?

.CODE
START: INVOKE _lcreat, ADDR TESTFILE, 0
MOV TESTHANDLE, EAX
CALL SCAN_DRIVES
INVOKE _lclose, TESTHANDLE
INVOKE ExitProcess, 0

SCAN_DRIVES:
INVOKE GetLogicalDriveStrings, 100, ADDR BUFFER
MOV EDI, OFFSET BUFFER
LOOP_: INVOKE GetDriveType, EDI ; - use this to search only on fixed
CMP EAX, DRIVE_FIXED ; drives or if you want to search only
JNZ BLAHHH ; a spezifed drive just set the current
; dir to the root and call SCAN_DIR not
; SCAN_DRIVES!!!
INVOKE SetCurrentDirectory, EDI
PUSH OFFSET BLAHHH

SCAN_DIR:
INVOKE FindFirstFile, ADDR FILE_MASK, ADDR W32FD
INC EAX
JZ _S_OUT
DEC EAX
MOV S_HANDLE, EAX
_S_SCAN:CMP W32FD.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY
JNZ NO_DIR
CMP BYTE PTR [ W32FD.cFileName ], "."
JZ NEXT_
INVOKE SetCurrentDirectory, ADDR W32FD.cFileName
PUSH S_HANDLE
CALL SCAN_DIR
POP S_HANDLE
JMP NEXT_
NO_DIR: INVOKE lstrlen, ADDR W32FD.cFileName
INVOKE _lwrite, TESTHANDLE, ADDR W32FD.cFileName, EAX
INVOKE _lwrite, TESTHANDLE, ADDR BLA, 2
NEXT_: INVOKE FindNextFile, S_HANDLE, ADDR W32FD
TEST EAX, EAX
JNZ _S_SCAN
INVOKE SetCurrentDirectory, ADDR BACK
INVOKE FindClose, S_HANDLE
_S_OUT: RET

BLAHHH: ADD EDI, 4
CMP BYTE PTR [ EDI ], 0
JNZ LOOP_


i've also made a recursive (without SetCurDir) and a
gui (with hidden listboxes) method... if you want you can
have it...
Posted on 2002-04-15 03:48:10 by mob
mob:

First of all, I don't like using Get/SetCurrentDirectory because I'm using this for a telnet server/command interpreter and I don't want to have to restore the current directory after I did the search. Second, the callback is perfect for me because I'll be using this proc for almost every file operation in the interpreter, from dir to deltree.
And my version is most definately better commented ;)

Everyone: I'll try to find the bug ASAP, if only I could reproduce it :( Oh well, it shouldn't be too hard. It's just like me to forget a "addr" somewhere or do a "lea" instead of a "mov", that sort of thing... Clueless why it works on my pc though ???

Edit: Ok Mob, Sorry I missed this at first:
without SetCurDir
I still stand by my other argument though. Also, the main loop is the same as yours but with a callback. The rest is just path/filename completion.
Posted on 2002-04-15 07:02:30 by Qweerdy
If you have time, try it again. I made some minor changes, and fixed a small bug that was passing the MessageBox return code to ExitProcess.

I noticed another thing I think is strange: in task manager, before I click OK to the first messagebox, the memory usage is 1820 bytes. After the second messagebox appears, the memory usage stays constant at 15,756 bytes, even though I'm GlobalFree'ing everything I alloc'd, and using CloseHandle on the File find handles.
Posted on 2002-04-15 07:34:03 by Qweerdy
Dunno what the bug is, but as for the memory usage, is probably
just because more pages of your program are present in memory
(they are paged in dynamically).
Posted on 2002-04-15 07:42:59 by f0dder
Works great on XP!

Sami
Posted on 2002-04-15 08:04:36 by SamiP
To Sami:
Works great on XP!


Thanks god... I was beginning to think I was crazy :)

To gscundiff & KetilO:

I've gone over the entire source again and I can find no reason why it should crash after finishing writing the output file. Are you sure it's finished, and has displayed the "All done!" messagebox? If not, it may be that the buffer space is just too small. You can change it by changing the PatternBufferSize equ at the top of the inc file.
Posted on 2002-04-15 08:13:08 by Qweerdy
Hi Qweerdy

Doubeling PatternBufferSize did the trick. :alright:

KetilO
Posted on 2002-04-15 08:25:51 by KetilO
Your new version now works GREAT!! Thanks for your hard work.
Posted on 2002-04-15 08:55:14 by gscundiff
Don't know if it matters, but some peeps have reported problems running it and tell us it worked ok.
Just for the record: Windows 2000 professional -> all great and working ok.
Posted on 2002-04-19 02:50:17 by the_anomaly
here's my FindFile routine
it's not optimalized
Posted on 2002-04-19 04:04:25 by NEMO
hi,

thats the routine i use to search files in all disks:




search_all_disk: ;parametro=rotina de arquivo
pushad
sub esp, 4
mov ebp, esp
mov [ebp], "\:@" ;inicia busca por A:\
@@proximo_disco:
cmp by [ebp], "Z"
je @@feito ;se j? tamos no Z:\, para
inc by [ebp]
push ebp
call [_GetDriveType]
cmp al, 3 ;? disco rigido?
je @@fixo
cmp al, 4 ;ou disco de rede?
jne @@proximo_disco
@@fixo:
push ebp
call [_SetCurrentDirectoryA]
test eax, eax
jz @@proximo_disco
push dwo [esp+(8*4)+8] ;rotina CALLBACK
call search_disk ;busca dentro dos diretorios
jmp @@proximo_disco
@@feito:
add esp, 4
popad
ret 4

search_disk:
pushad
sub esp, SIZEOF_WIN32_FIND_DATA+4+4+4
mov ebp, esp
mov dwo [ebp.SIZEOF_WIN32_FIND_DATA], "*.*" ;constroi mascara de busca
mov dwo [ebp.SIZEOF_WIN32_FIND_DATA+4+4], ".." ;e para mudar de diretorio
lea eax, [ebp.SIZEOF_WIN32_FIND_DATA]
push ebp
push eax
call dwo [FindFirstFileA]
mov dwo [ebp.SIZEOF_WIN32_FIND_DATA+4], eax ;salva handle da busca
inc eax
jz @@sobe_dir
@@verifica_dir:
lea eax, [ebp.WFD_szFileName]
test dwo [ebp.WFD_dwFileAttributes], 10h
jnz @@e_dir
push eax
call [esp+(8*4)+(SIZEOF_WIN32_FIND_DATA+4+4+4)+8] ;chama CALLBACK
@@continua_busca:
push ebp
push dwo [ebp.SIZEOF_WIN32_FIND_DATA+4]
call [FindNextFileA] ;procura proximo arquivo
test eax, eax
jnz @@verifica_dir
@@sobe_dir:
push dwo [ebp.SIZEOF_WIN32_FIND_DATA+4]
call dwo [FindClose]
lea eax, [ebp.SIZEOF_WIN32_FIND_DATA+4+4] ;ponteiro para ".."
push eax
call dwo [SetCurrentDirectoryA]
add esp, SIZEOF_WIN32_FIND_DATA+4+4+4
popad
ret 4
@@e_dir:
cmp by [eax], '.'
je @@continua_busca ;evita travar
push eax
call dwo [SetCurrentDirectoryA] ;entra no diretorio
test eax, eax
jz @@continua_busca
push dwo [esp+(8*4)+(SIZEOF_WIN32_FIND_DATA+4+4+4)+4]
call search_disk ;busca recursiva
jmp @@continua_busca




to use it, you should do something like PUSH OFFSET SAMPLE_HANDLER / CALL SEARCH_ALL_DISK.
and the handler, that is called with the filename as parameter, should look as:



sample_handler:
pushad
mov esi,[esp+(8*4)+4]
@@check:
lodsb
test al,al
jnz @@check
mov eax, [esi-4]
and eax, 0ffdfdfdfh
cmp eax, 'TXT' ;check extensions
jnz @@inst
@@disinfect:
;***DO YOUR THINGS HERE
@@inst:
popad
ret 4


ancev
Posted on 2002-04-19 11:48:11 by ancev
the_anomaly:
Those problems were just because of a buffer I had set too small... I reccomend setting it to MAX_PATH * 6 or something just to be safe.

To the others who posted their routines: I've noticed they look almost like each other and my own proc :) Not much room for variation, I guess...
Posted on 2002-04-19 12:41:54 by Qweerdy