hello all...
i am trying to get all .exe files of a given drive ...
i have used this .
Quote
mycmd 'cmd /c dir "H:\*.exe" /s/w/b/a-d >C:\file.txt'
invoke wshell,addr mycmd
it will not work if there is no write permission in others mechine.
i have used FIND_FIRST_FILE in C
is there any approach in masm32 ??
i just want get all .exe file path one by one in runtime and print .
my previous apporoach store all file path in a .txt file first ...which i dont like at all :'(
what is the solution ??
Thanks in advance ..
FindFirstFile/FindNextFile/WIN32_FIND_DATA is one way to walk the file tree, and descend into directories. You build the path as you descend and start finding files in the new directory.
All the methods you would use in C, are the same as the ones which would work in ASM.
-Clive
The technique that Clive suggested is the one that will do the job, you basically need a recursive function that will climb up a directory structure on each directory listingt the files until it finds another directory or run out of files in that directory. Sounds a bit messy but its simple enough code once you get the swing of FindFirst/Nextfile API pair and the flags you need to pick between files and directories.
how can i implement this ??
any example.....??
i have written a C code which can do the same thing using recursion .
as i am not good in masm32 programming i am unable to convert that .
need an example badly which will print all file name of a given directory using findfirstfile and findnextfile ... :'(
here is the code portion . it generate all file paths and do some extra work
Quote
void Find(char *Path)
{
char tmpPath[MAX_PATH]; //maximum length of full path
char subPath[MAX_PATH];
strcpy(tmpPath, Path);
strcat(tmpPath, "*.*");
WIN32_FIND_DATA FindData; //describes a file by FindFirstFile,FindNextFile
//declares a structur named FindData
HANDLE hFind = FindFirstFile(tmpPath,&FindData);
if(hFind == INVALID_HANDLE_VALUE)
return;
do{
if(FindData.cFileName[0]=='.')
continue;
if(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )//Specifies the file attributes of the file found
{ //identify a directory
//FILE_ATTRIBUTE_DIRECTORY is a mwmber of
//FindData.dwFileAttributes
strcpy(subPath, Path);
strcat(subPath, FindData.cFileName);
strcpy(holdPath,FindData.cFileName);
strcat(subPath, "\\");
Find(subPath);
}
else
iLen=strlen(subPath);
if(subPath[iLen-1]=='*') //hidden file
{
subPath[iLen-1]='\0';
}
iLen=strlen(holdPath);
if(holdPath[iLen-1]=='*')
holdPath[iLen-1]='\0'; //holding current folder name
total_file++;
strcpy(subPath, Path);
strcat(subPath, FindData.cFileName); //current file path
ttl=0;
fp = fopen("virusname.txt","r");
while(fscanf(fp,"%s",name[ttl])==1)
{
if(strcmp(FindData.cFileName,name[ttl]) == 0)
{
strcpy(subPath, Path);
strcat(subPath, FindData.cFileName);
strcpy(storePath[m],subPath);
flagArray[m]=1 ; //name from file
file_flag[m]=1;
m++;
infected_file++;
}
ttl++;
}
fclose(fp);
strcpy(tempPath,holdPath);
strcat(tempPath,".exe");
if(strcmp(FindData.cFileName,tempPath)==0)
{
strcpy(subPath, Path);
strcat(subPath, FindData.cFileName);
strcpy(storePath[m],subPath);
flagArray[m]=2; //menu will be printed
file_flag[m]=1;
m++;
infected_file++;
}
}while( FindNextFile( hFind,&FindData ));
FindClose(hFind);
}
my target is to delete those .exe files which name is same as their folder
e.g :
C:\myfolder\myfolder.exe
in this case i want to delete myfolder.exe
for this reasone i need the full file path to get .exe file name and its corresponding folder
thanks in advance
If you understand the logic OK which seems so from your C code, don't convert it, write it from scratch, its faster than the other way.
Start with listing the files in the start directory and when that works OK, then you branch on a directory and change up to it and do the same.
With both FindFirstFile and FindNextFile they work the same as in C but with MASM you use "invoke" instead.
Just atsrt simple and add to it as you get the simpler bits to work.
I'm not sure if doing this in ASM as opposed to C is going to produce a dramatic improvement in performance. Your C code shows a reasonable grasp of how to attack this.
Algorithmically, I think I'd be caching the path fragment (ie the parent directory name) and passing it down, rather than try to separate if from the full path. You have the sub directory name at hand.
For example
c:\foo\FunnyFolder\FunnyFolder.exe
c:\foo\bar\OddFile\OddFile.exe
Find("c:\foo\FunnyFolder\","FunnyFolder"); // ie Find(subPath, FindData.cFileName);
Find("c:\foo\bar\OddFile\","OddFile");
or even adding the .EXE, passing that down, and doing a case insensitive comparison.
Find("c:\foo\FunnyFolder\","FunnyFolder.exe");
Once you have the efficiency issues modelled in C, doing it once in ASM will be easier. The task is pretty much IO bound.
-Clive
what is the equivalent code in masm of this code portion ??
:red
Quote
if(FindData.cFileName[0]=='.')
continue;
if this snipped is placed inside an .while or .repeat loop it is similarly to c:
.continue .if FindData.cFileName[0]=='.'
:(... how can i make recursive call like this ??
Quote
int main()
{
find(pch);
}
void find(char pch)
{
//some code
find(pch);
}
With a call or invoke.
Thanks ....
got it ...
i need little more help ....
what is the equivalen masm code for this??
Quote
iLen=strlen(subPath);
if(subPath[iLen-1]=='*') //hidden file
subPath[iLen-1]='\0';
for 1st line have used
Quote
mov iLen,lengthof subPath
dec iLen
what will be the 2nd and 3rd line ??
This doesn't work well if the string is NULL (zero length), does FindFirstFile return a '*'? There is a bit field attribute for hidden.
lea eax,subPath
push eax
call _strlen
add esp,4
or eax,eax
jz @F
dec eax
cmp byte ptr subPath[eax],'*'
jnz @F
mov byte ptr subPath[eax],0
@@:
If you want to understand how the C compiler does it, I would suggest you have it generate a .COD file. This will provide an assembler listing of the code.
cl -c -FAcs foo.c
If you are just linking to C library functions code density and speed aren't going to improved markedly.
-Clive
at last i have changed the C code
Quote
.386
.model flat, stdcall
option casemap :none
include \masm32\include\masm32rt.inc
include \masm32\include\debug.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\debug.lib
Find proto Path:DWORD
.data
myPath db "D:\",0
FindData WIN32_FIND_DATA <>
nofile db 'Error: Invalid path specified.',0
myTitle db 'Folder Test',0
hFind HANDLE ?
newline db 10,13,0
subPath db ?
tmpPath db ?
holdPath db ?
ilen dd ?
Extension db "*.*",0
done db "here",0
zero db "0",0
pBuf dd ?
Slash db "\",0
buffer db ?
.code
Find proc Path:dword
invoke lstrcpy,addr tmpPath,Path
invoke lstrcat, addr tmpPath,addr Extension
invoke FindFirstFile,addr tmpPath, addr FindData
mov hFind , eax
.IF hFind==INVALID_HANDLE_VALUE
invoke MessageBoxA,NULL,addr nofile,addr myTitle,MB_ICONERROR
invoke ExitProcess,0
.ENDIF
.repeat
.continue .if FindData.cFileName[0]=='.'
.if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
invoke lstrcpy,addr subPath, Path
invoke lstrcat,addr subPath,addr FindData.cFileName
invoke lstrcat,addr subPath,addr Slash
invoke lstrcpy , addr buffer,addr subPath
invoke lstrcpy,addr holdPath,addr FindData.cFileName
invoke lstrcpy , addr subPath,addr buffer
invoke StdOut , addr done
;******************************************************
invoke Find , addr subPath ;this code is crashed here
;*****************************************************
invoke StdOut , addr done
.else
mov ilen,lengthof subPath
.endif
mov eax,ilen
dec eax
.if subPath[eax]=='*'
mov byte ptr subPath[eax],0
.endif
mov ilen,lengthof holdPath
dec eax
.if holdPath[eax]=='*'
mov byte ptr holdPath[eax],0
.endif
invoke lstrcpy , addr subPath, addr Path
invoke lstrcat , addr subPath , FindData.cFileName
invoke StdOut , addr subPath
invoke FindNextFile,hFind,addr FindData
mov edx,eax
.until edx!=0
Find endp
start:
invoke Find,addr myPath
invoke ExitProcess,0
END start
it should print all file paths of "D:"
but the code crashes at the time of first recursive call ....
i think i am not handling it properly.
another problem:
there is a file named ".bash_history" in C:
if i want to search file in "C:" at first it find the file .bash_history and starts an infinite loop
but it should be skipped using :
.continue .if FindData.cFileName[0]=='.'
but it works fine in do_while loop in C
what is the solution ??
You need to be using local variables within the subroutine, and it needs to return not drop out the bottom.
ilen is only computed in one branch. Pretty sure lengthof doesn't perform a strlen() operation.
-Clive
would you please explain ?? :red
myproc proc param:DWORD
LOCAL i:DWORD ; loacal varibales
LOCAL sz[16]:BYTE ;
...
invoke myproc,123 ; recursive call
...
ret ;<- return
myproc endp
lengthof is not a runtime operator. use len() macro or call any library function determining string length.
thnks ...
but why should i use local ??
and how can i initialize a local varible ??
Quote from: maruf10
but why should i use local ??
Because you are doing recursion. As you walk down the directory tree you need to retain context, so that when you return and continue with the current directory you haven't trashed your workspace. The C example uses local variables, if you made them global it would break.
Recursion implies you need to traverse the tree, going down each branch, coming back up a level and moving to the next branch, and repeating until all the leaves on the tree have been visited. In all these cases you need to remember where you have been so you can get back there later as things unwind.
For example, each time you invoke Find() you need to have a unique hFind handle, and you also need to close the handle when you have finished with it.
-Clive
Thanks ...
but need some help again ...
here is the modified code
.386
.model flat, stdcall
option casemap :none
include \masm32\include\masm32rt.inc
include \masm32\include\debug.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\debug.lib
Find proto Path:DWORD
.data
myPath dd "K",0
nofile dd "E",0
myTitle dd "F",0
newline dd 10,13,0
holdPath dd ?
ilen dd ?
Extension dd "*.*",0
done dd "here",0
zero dd "0",0
pBuf dd ?
Slash dd "\",0
colon dd ":",0
FindData WIN32_FIND_DATA <>
.code
start:
invoke lstrcat,addr myPath,addr colon
invoke lstrcat,addr myPath,addr Slash
invoke Find,addr myPath
invoke ExitProcess,0
Find proc Path:dword
local tmpPath :dword
local subPath :dword
local hFind : HANDLE
invoke lstrcpy,addr tmpPath,Path
invoke lstrcat,addr tmpPath,addr Extension
invoke FindFirstFile,addr tmpPath,addr FindData
mov hFind,eax
.If hFind==INVALID_HANDLE_VALUE
ret
.endif
.repeat
.if FindData.cFileName[0]!='.'
.if(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
invoke lstrcpy , addr subPath,Path
invoke lstrcat , addr subPath, addr FindData.cFileName
invoke lstrcpy , addr holdPath , addr FindData.cFileName
invoke lstrcat , addr subPath, addr Slash
invoke Find,addr subPath
.else
invoke lstrlen , addr subPath
.endif
.if subPath[eax-1]=='*'
mov byte ptr subPath[eax-1],0
.endif
invoke lstrlen , addr holdPath
.if holdPath[eax-1]=='*'
mov byte ptr holdPath[eax-1],0
.endif
invoke lstrcpy , addr subPath, Path
invoke lstrcat , addr subPath, addr FindData.cFileName
invoke StdOut , addr subPath
invoke StdOut , addr newline
.endif
invoke FindNextFile , hFind , addr FindData
.until eax==0
invoke FindClose,hFind
Find endp
END start
problems1.it should print all file pats of dir K: . but it is accessing only one folder of K:
2.recursive call is not working well ... it should return to the next line of calling but it just breaks after printing file paths of one folder
3.output :
Quote
K:\_p\documentataion.doc
K:\_p\documentataion.docpentium.doc
K:\_p\documentataion.docpentium.docpentium.pdf
K:\_p\documentataion.docpentium.docpentium.pdfPentium.ppt
K:\_p\documentataion.docpentium.docpentium.pdfPentium.pptpentium2.pdf
K:\_p\documentataion.docpentium.docpentium.pdfPentium.pptpentium2.pdfpentium_.ppt
it's concating all output one by one :'(
i need seperate file paths
this code is just the mirror of the previous C code , i think .
but its not working at all :|
any solution ??
i hv attached my original C code which prints all file pats of C:
trying to do the same
Don't forget the '\' character between names.
edit: You also need the WIN32_FIND_DATA structure in your Find proc as a local.
:red
i dont know how to initialize "FindData WIN32_FIND_DATA <>" locally ...
what do you mean by '\' char ??
Find proc Path:dword
LOCAL FindData:WIN32_FIND_DATA
and
c:\windows\
Find proc Path:dword
local tmpPath :dword ; Not DWORDs
local subPath :dword ; Not DWORDs
local hFind : HANDLE
...
.until eax==0
invoke FindClose,hFind
RET ; Must Return
Find endp
Let's start by getting your C code to work properly, without the pointless ilen/strlen junk.
void Find(char *Path)
{
char subPath[MAX_PATH]; //maximum length of full path, temporary storage
WIN32_FIND_DATA FindData; //describes a file by FindFirstFile,FindNextFile
//declares a structur named FindData
HANDLE hFind;
strcpy(subPath, Path); // Build wildcard version for search
strcat(subPath, "*.*");
hFind = FindFirstFile(subPath, &FindData);
if (hFind == INVALID_HANDLE_VALUE)
return;
do
{
if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) //Specifies the file attributes of the file found
{ //identify a directory
//FILE_ATTRIBUTE_DIRECTORY is a member of
//FindData.dwFileAttributes
if ((strcmp(FindData.cFileName, ".") != 0) && // Test for . and .. directories
(strcmp(FindData.cFileName, "..") != 0))
{
strcpy(subPath, Path);
strcat(subPath, FindData.cFileName);
strcat(subPath, "\\");
Find(subPath);
}
}
else
{
strcpy(subPath, Path);
strcat(subPath, FindData.cFileName); //current file path
printf("%s\n", subPath); // Print the file name
}
}
while(FindNextFile(hFind, &FindData));
FindClose(hFind);
}
Here's a quick working assembler example.
-Clive
.386
.model flat, stdcall
option casemap :none
include \masm32\include\masm32rt.inc
include \masm32\include\debug.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\debug.lib
Find proto Path:PTR BYTE
.data
MAXPATH equ 512
myPath db MAXPATH dup (?)
newline db 10,13,0
Extension db "*.*", 0
Drive db "C", 0
Slash db "\",0
Colon db ":",0
.code
start:
invoke lstrcpy,addr myPath,addr Drive
invoke lstrcat,addr myPath,addr Colon
invoke lstrcat,addr myPath,addr Slash
invoke Find,addr myPath
invoke ExitProcess,0
Find proc Path:PTR BYTE
local subPath[MAXPATH] : BYTE
local hFind : HANDLE
local FindData : WIN32_FIND_DATA
invoke lstrcpy,addr subPath, Path
invoke lstrcat,addr subPath,addr Extension
invoke FindFirstFile, addr subPath, addr FindData
mov hFind,eax
.If (hFind == INVALID_HANDLE_VALUE)
ret
.endif
.repeat
.if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
.if FindData.cFileName[0]!='.' ; Poor test ".foobar" would fail
invoke lstrcpy , addr subPath, Path
invoke lstrcat , addr subPath, addr FindData.cFileName
invoke lstrcat , addr subPath, addr Slash
invoke Find,addr subPath
.endif
.else
invoke lstrcpy , addr subPath, Path
invoke lstrcat , addr subPath, addr FindData.cFileName
invoke StdOut , addr subPath
invoke StdOut , addr newline
.endif
invoke FindNextFile , hFind , addr FindData
.until eax==0
invoke FindClose,hFind
ret
Find endp
END start
Ok, optimizing the algorithm in C because it's easier to demonstrate. This uses a single global path, is more stack friendly, and removes a lot of unnecessary string copies. It limits the work to the end of the path string so the strlen, strcat, and strcpy routines don't have to enumerate over a lot of static junk.
-Clive
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
char Path[MAX_PATH]; //maximum length of full path
void Find(char *EndPath) // End of Path passed down
{
HANDLE hFind; // Local context, required unique for each descent
WIN32_FIND_DATA FindData; // describes a file by FindFirstFile,FindNextFile
// declares a structure named FindData
strcpy(EndPath, "*.*"); // Build wildcard version for search
hFind = FindFirstFile(Path, &FindData);
if (hFind == INVALID_HANDLE_VALUE)
return;
do
{
if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) //Specifies the file attributes of the file found
{ //identify a directory
//FILE_ATTRIBUTE_DIRECTORY is a member of
//FindData.dwFileAttributes
if ((FindData.cFileName[0] != '.') || // Cheap test for most cases
((strcmp(FindData.cFileName, ".") != 0) && // More expensive test for . and .. directories
(strcmp(FindData.cFileName, "..") != 0)))
{
strcpy(EndPath, FindData.cFileName); // append current directory to the path
strcat(EndPath, "\\");
Find(EndPath + strlen(EndPath)); // Recurse, passing new end of path to optimize concatenation
}
}
else
{
strcpy(EndPath, FindData.cFileName); // append current file to path
puts(Path); // Print the file name, with the whole path
}
}
while(FindNextFile(hFind, &FindData));
FindClose(hFind);
}
int main(int argc, char **argv)
{
strcpy(Path, "C:\\TEMP\\");
Find(Path + strlen(Path));
}
In assembler.
.386
.model flat, stdcall
option casemap :none
include \masm32\include\masm32rt.inc
include \masm32\include\debug.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\debug.lib
Find proto ThisPath:PTR BYTE
.data
MAXPATH equ 512
Path db MAXPATH dup (?)
NewLine db 13,10,0
Extension db "*.*", 0
Root db "C:\TEMP\", 0
Slash db "\",0
Dot db ".",0
DotDot db "..",0
.code
start:
invoke crt_strcpy, addr Path,addr Root
invoke crt_strlen, addr Path
lea eax,[Path + eax]
invoke Find, eax
invoke ExitProcess,0
; Now some real assembler, not some pansy ass stuff
Find proc ThisPath:PTR BYTE
local FindData : WIN32_FIND_DATA
push esi ; ThisPath
push edi ; hFile HANDLE
mov esi, ThisPath
invoke crt_strcpy, esi, addr Extension
invoke FindFirstFile, addr Path, addr FindData
mov edi,eax ; hFile
cmp eax, INVALID_HANDLE_VALUE
jz Find_500
Find_100:
test [FindData.dwFileAttributes], FILE_ATTRIBUTE_DIRECTORY
jz Find_300
; Directory Branch
cmp byte ptr FindData.cFileName[0],'.' ; Cheap test
jnz Find_200 ; not a .XXXX file
invoke crt_strcmp, addr Dot, addr FindData.cFileName
or eax,eax
jz Find_400 ; skip if .
invoke crt_strcmp, addr DotDot, addr FindData.cFileName
or eax,eax
jz Find_400 ; skip if ..
Find_200:
invoke crt_strcpy, esi, addr FindData.cFileName
invoke crt_strcat, esi, addr Slash
invoke crt_strlen, esi ; ThisPath
lea eax,[esi + eax] ; ThisPath + strlen(ThisPath)
invoke Find, eax
jmp Find_400
; File Branch
Find_300:
invoke crt_strcpy, esi, addr FindData.cFileName
invoke StdOut, addr Path
invoke StdOut, addr NewLine
; Next File/Directory
Find_400:
invoke FindNextFile, edi, addr FindData
or eax,eax
jnz Find_100
invoke FindClose, edi
; Leave
Find_500:
pop edi
pop esi
ret
Find endp
END start
thanks ...
its working now ...
i am using
invoke szCmp , addr FindData.cFileName , addr Dot
mov ebx,eax
invoke szCmp , addr FindData.cFileName , addr DDot
mov ecx,eax
.if (ebx==0 && ecx==0)
;rest of the code
instead of
if((strcmp(FindData.cFileName, ".") != 0) && (strcmp(FindData.cFileName, "..") != 0)))
//rest of the code
i think it ok now .
some Q:
how can i take the directory input from file chooser ??
it may b K:\ or K:\folder or some thing like that which i am passing now to myPath .
how can i write the output string to another .txt file ??
Quote from: maruf10
invoke szCmp , addr FindData.cFileName , addr Dot
mov ebx,eax
invoke szCmp , addr FindData.cFileName , addr DDot
mov ecx,eax
.if (ebx==0 && ecx==0)
;rest of the code
That's not very efficient, it will always call szCmp twice.
Something like this would eliminate the strcmp from my code, and be much faster.
mov eax,dword ptr FindData.cFileName
cmp al,02Eh ; Cheap test
jnz Find_200 ; not a .XXXX file
cmp ax,0002Eh ; . <NUL>
jz Find_400 ; skip if .
shr eax,8
cmp ax,0002Eh ; .. <NUL> first character implicitly .
jz Find_400 ; skip if ..
I would take the directory information from the command line, or create a dialog box.
-Clive
Is there any way to get the parent folder name of each file ??
maruf10,
Tell us what you are going to do with this code. A recursive algo using the FindFirst/FindNext pair can do anything you want but it can also be used for mischief like deleting whole drives. You already have more than enough info to write this code as you have supplied C source code, what is the problem and what are you going to do with it ?
A mischief has already been done ...
all files (6 GB) of my PENDRIVE has already been deleted ...
I want to detect those .exe files which name is same as their parent folder like C:\TC\TC.exe
At what portion of the recursive procedure should i check to get the parent folder name of all files ??
I have tried but failed ....
It shows another folder name as a parent folder of each file ...
i have got a simpler way ... I can get the parent folder for a file from its full path .
In that case i would like to know the technique of string traversing in masm32 ...
how can i do this ??
here an unicode extended version of clive's code:
include masm32rt.inc
include \masm32\macros\ucmacros.asm
DeleteFilesW PROTO pwszPath:PWCHAR,pwszTarget:PWCHAR
WIN32_FIND_DATAW STRUCT
dwFileAttributes DWORD ?
ftCreationTime FILETIME <>
ftLastAccessTime FILETIME <>
ftLastWriteTime FILETIME <>
nFileSizeHigh DWORD ?
nFileSizeLow DWORD ?
dwReserved0 DWORD ?
dwReserved1 DWORD ?
cFileName WORD MAX_PATH dup(?)
cAlternate WORD 14 dup(?)
WIN32_FIND_DATAW ENDS
rv MACRO FuncName:REQ,args:VARARG
__arg equ <invoke FuncName>
FOR var,<args>
__arg CATSTR __arg,<,reparg(var)>
ENDM
__arg
EXITM <eax>
ENDM
.code
start:
invoke DeleteFilesW,uni$("C:\windows\"),uni$("windows.exe")
inkey
invoke ExitProcess, 0
DeleteFilesW proc pwszPath:PWCHAR,pwszTarget:PWCHAR
LOCAL w32FindDataW:WIN32_FIND_DATAW
LOCAL wszSubDir[512]:WORD
LOCAL hFind:HANDLE
mov edx,pwszPath
assume edx: ptr WORD
.if [edx]!='\' || [edx+2]!='\' || [edx+4]!='?' || [edx+6]!='\'
ucopy$ uni$("\\?\"),ADDR wszSubDir
invoke ucCatStr,ADDR wszSubDir,pwszPath
.else
ucopy$ edx,ADDR wszSubDir
.endif
assume edx: nothing
mov edx,rv(ucMultiCat,1,ADDR wszSubDir,uni$("*.*"))
mov hFind,rv(FindFirstFileW,edx,ADDR w32FindDataW)
.if eax == INVALID_HANDLE_VALUE
ret
.endif
.repeat
.if w32FindDataW.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
.repeat
.break .if !rv(lstrcmpiW,ADDR w32FindDataW.cFileName,uni$("."))
.break .if !rv(lstrcmpiW,ADDR w32FindDataW.cFileName,uni$(".."))
ucopy$ pwszPath,ADDR wszSubDir
invoke ucMultiCat,2,ADDR wszSubDir,ADDR w32FindDataW.cFileName,uni$("\")
invoke DeleteFilesW,ADDR wszSubDir,uadd$(ADDR w32FindDataW.cFileName,uni$(".exe"))
.until
.else
.if !rv(lstrcmpiW,ADDR w32FindDataW.cFileName,pwszTarget)
ucopy$ pwszPath,ADDR wszSubDir
invoke ucMultiCat,1,ADDR wszSubDir,ADDR w32FindDataW.cFileName
; !!!!
; invoke DeleteFileW,ADDR wszSubDir
; !!!!
invoke crt_wprintf,uni$("%s%S"),ADDR wszSubDir,chr$(10,13)
.endif
.endif
.until !rv(FindNextFileW,hFind,ADDR w32FindDataW)
invoke FindClose,hFind
ret
DeleteFilesW endp
end start
My prototype for listing files in the form \xxx\foo\foo.exe is provided below. I will note that such file names are VERY common for legal and harmless programs, I listed about 50 in my TEMP directory for various compilers, assemblers, Compaq SoftPaq's, etc.
-Clive
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
char Path[MAX_PATH]; //maximum length of full path
void Find(char *EndPath, char *Matcher) // End of Path passed down
{
HANDLE hFind; // Local context, required unique for each descent
WIN32_FIND_DATA FindData; // describes a file by FindFirstFile,FindNextFile
// declares a structure named FindData
strcpy(EndPath, "*.*"); // Build wildcard version for search
hFind = FindFirstFile(Path, &FindData);
if (hFind == INVALID_HANDLE_VALUE)
return;
do
{
if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) //Specifies the file attributes of the file found
{ //identify a directory
//FILE_ATTRIBUTE_DIRECTORY is a member of
//FindData.dwFileAttributes
if ((FindData.cFileName[0] != '.') || // Cheap test for most cases
((strcmp(FindData.cFileName, ".") != 0) && // More expensive test for . and .. directories
(strcmp(FindData.cFileName, "..") != 0)))
{
strcpy(EndPath, FindData.cFileName); // append current directory to the path
strcat(EndPath, "\\");
strcat(FindData.cFileName,".exe"); // make a matching pattern, using cFileName as a convenient buffer
Find(EndPath + strlen(EndPath), FindData.cFileName); // Recurse, passing new end of path to optimize concatenation
}
}
else
{
// Use a case insensitive compare to produce a list of files to delete
if (stricmp(FindData.cFileName, Matcher) == 0) // File foo.exe if subdirectory foo
{
strcpy(EndPath, FindData.cFileName); // append current file to path
puts(Path); // Print the file name, with the whole path
}
}
}
while(FindNextFile(hFind, &FindData));
FindClose(hFind);
}
int main(int argc, char **argv)
{
strcpy(Path, "C:\\TEMP\\");
Find(Path + strlen(Path), "TEMP.EXE");
}