The MASM Forum Archive 2004 to 2012

General Forums => The Workshop => Topic started by: maruf10 on March 30, 2010, 11:30:22 AM

Title: how to get all .exe files name of a given drive ??
Post by: maruf10 on March 30, 2010, 11:30:22 AM
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 ..
Title: Re: how to get all .exe files name of a given drive ??
Post by: clive on March 30, 2010, 11:52:19 AM
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
Title: Re: how to get all .exe files name of a given drive ??
Post by: hutch-- on March 30, 2010, 12:04:58 PM
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.
Title: Re: how to get all .exe files name of a given drive ??
Post by: maruf10 on March 30, 2010, 12:09:17 PM
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
Title: Re: how to get all .exe files name of a given drive ??
Post by: hutch-- on March 30, 2010, 12:39:02 PM
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.
Title: Re: how to get all .exe files name of a given drive ??
Post by: clive on March 30, 2010, 04:10:20 PM
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
Title: Re: how to get all .exe files name of a given drive ??
Post by: maruf10 on March 30, 2010, 06:12:23 PM
what is the equivalent code in masm of this code portion ??
:red
Quote

if(FindData.cFileName[0]=='.')
         continue;

Title: Re: how to get all .exe files name of a given drive ??
Post by: qWord on March 30, 2010, 06:19:51 PM
if this snipped is placed inside an .while or .repeat loop it is similarly to c:
.continue .if FindData.cFileName[0]=='.'
Title: Re: how to get all .exe files name of a given drive ??
Post by: maruf10 on March 30, 2010, 07:32:18 PM
 :(... how can i make recursive call like this ??

Quote

int main()
{
     find(pch);
}

void find(char pch)
{
    //some code
     find(pch);
}
Title: Re: how to get all .exe files name of a given drive ??
Post by: clive on March 30, 2010, 08:18:20 PM
With a call or invoke.
Title: Re: how to get all .exe files name of a given drive ??
Post by: maruf10 on March 30, 2010, 08:39:03 PM
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 ??
Title: Re: how to get all .exe files name of a given drive ??
Post by: clive on March 30, 2010, 08:50:52 PM
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
@@:

Title: Re: how to get all .exe files name of a given drive ??
Post by: clive on March 30, 2010, 08:58:06 PM
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

Title: Re: how to get all .exe files name of a given drive ??
Post by: maruf10 on March 31, 2010, 08:08:50 AM
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 ??
Title: Re: how to get all .exe files name of a given drive ??
Post by: clive on March 31, 2010, 11:58:06 AM
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
Title: Re: how to get all .exe files name of a given drive ??
Post by: maruf10 on March 31, 2010, 02:21:21 PM
would you please explain ?? :red
Title: Re: how to get all .exe files name of a given drive ??
Post by: qWord on March 31, 2010, 02:29:54 PM
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.
Title: Re: how to get all .exe files name of a given drive ??
Post by: maruf10 on March 31, 2010, 03:45:37 PM
thnks ...
but why should i use local ??
and how can i initialize a local varible ??
Title: Re: how to get all .exe files name of a given drive ??
Post by: clive on March 31, 2010, 04:20:27 PM
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
Title: Re: how to get all .exe files name of a given drive ??
Post by: maruf10 on April 01, 2010, 11:19:22 AM
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



problems
1.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
Title: Re: how to get all .exe files name of a given drive ??
Post by: sinsi on April 01, 2010, 11:43:38 AM
Don't forget the '\' character between names.

edit: You also need the WIN32_FIND_DATA structure in your Find proc as a local.
Title: Re: how to get all .exe files name of a given drive ??
Post by: maruf10 on April 01, 2010, 12:06:21 PM
 :red
i dont know how to initialize "FindData  WIN32_FIND_DATA <>" locally ...
what do you mean by '\' char ??
Title: Re: how to get all .exe files name of a given drive ??
Post by: oex on April 01, 2010, 12:55:30 PM
Find proc Path:dword

LOCAL FindData:WIN32_FIND_DATA

and

c:\windows\
Title: Re: how to get all .exe files name of a given drive ??
Post by: clive on April 01, 2010, 03:47:42 PM

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
Title: Re: how to get all .exe files name of a given drive ??
Post by: clive on April 01, 2010, 04:14:05 PM
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);
}
Title: Re: how to get all .exe files name of a given drive ??
Post by: clive on April 01, 2010, 05:21:12 PM
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
Title: Re: how to get all .exe files name of a given drive ??
Post by: clive on April 02, 2010, 01:59:51 AM
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));
}
Title: Re: how to get all .exe files name of a given drive ??
Post by: clive on April 02, 2010, 03:07:27 AM
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
Title: Re: how to get all .exe files name of a given drive ??
Post by: maruf10 on April 02, 2010, 02:30:58 PM
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 ??
Title: Re: how to get all .exe files name of a given drive ??
Post by: clive on April 02, 2010, 02:36:00 PM
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
Title: Re: how to get all .exe files name of a given drive ??
Post by: maruf10 on April 11, 2010, 01:16:19 PM
Is there any way to get the parent folder name of each file ??
Title: Re: how to get all .exe files name of a given drive ??
Post by: hutch-- on April 11, 2010, 01:38:28 PM
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 ?
Title: Re: how to get all .exe files name of a given drive ??
Post by: maruf10 on April 11, 2010, 03:07:18 PM
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 ??
Title: Re: how to get all .exe files name of a given drive ??
Post by: qWord on April 12, 2010, 03:38:42 PM
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
Title: Re: how to get all .exe files name of a given drive ??
Post by: clive on April 12, 2010, 05:01:47 PM
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");
}