.386 .model flat, stdcall option casemap :none include \masm32\include\windows.inc include \masm32\include\wininet.inc include \masm32\macros\macros.asm include \masm32\macros\windows.asm uselib kernel32,masm32,user32 includelib \masm32\lib\irvine32.lib ;либа и процедуры для отладки DumpRegs PROTO findAll PROTO :dword GetExt PROTO :dword,:dword WriteString PROTO Crlf PROTO .const extnum equ 5 ;может на структуры переделать и lengthof? в общем это к-тво расширений .data fd WIN32_FIND_DATA <> ;FILE_ATTRIBUTE_DIRECTORY startDir db "E:",0 ;стартовая папка mask0 db "*",0 ;маска поиска buff db 512 dup (0) ;искомые расширения ext1 db "jpg",0 ext2 db "doc",0 ext3 db "docx",0 ext4 db "mp3",0 ext5 db "torrent",0 ;указатели pext1 dd offset ext1 pext2 dd offset ext2 pext3 dd offset ext3 pext4 dd offset ext4 pext5 dd offset ext5 ;счетчики cext1 dd 0 cext2 dd 0 cext3 dd 0 cext4 dd 0 cext5 dd 0 heapH dd 0 ;heap handle lpMem dd 0 ; pointer to memory len1 dd 0 ;длина имени фаела hFile dd 0 .code Start: push offset startDir call findAll invoke GetProcessHeap mov heapH,eax invoke HeapAlloc,heapH,HEAP_ZERO_MEMORY,1024 mov lpMem,eax invoke wsprintf,lpMem,chr$("jpg - %d,doc - %d,docx - %d,mp3 - %d,torrent - %d"),cext1,cext2,cext3,cext4,cext5 invoke MessageBox,0,lpMem,0,0 invoke HeapFree,heapH,0,lpMem invoke ExitProcess,0 findAll PROC p1:dword local buf[MAX_PATH]:byte ;рабочий буфер local directory[MAX_PATH]:byte ;текущая директория local directoryRes[MAX_PATH]:byte ;резервный буфер local hFindFile:dword invoke lstrcpy,addr buf,p1 ;копируем то, на что указывает буфер (т.е. переданную директорию) invoke lstrcpy,addr directory,addr buf ;копируем это еще раз, для передачи в функцию invoke lstrcpy,addr directoryRes,addr buf ;и еще раз, для резерва invoke lstrcat,addr buf,chr$("\") ;добавляем слеш invoke lstrcat,addr buf,offset mask0 ;добавляем маску invoke lstrlen,p1 ;вычисляем длину папки с маской mov esi,eax add esi,sizeof mask0 ;добавляем длину маски mov byte ptr buf[esi],0 ;добавляем нуллбайт invoke FindFirstFile,addr buf,offset fd mov hFindFile,eax .if eax==INVALID_HANDLE_VALUE ;если ошибка print "some error with FindFirstFile" ;уведомляем и выходим ret .endif ;проверять только через and , а не через = !! .if fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ;если это папка invoke lstrcmp,addr fd.cFileName,chr$(".") ;это "."? идем дальше test eax,eax jz FNDNext invoke lstrcmp,addr fd.cFileName,chr$("..") ;это ".."? также пропускаем test eax,eax jz FNDNext invoke lstrcat,addr directory,chr$("\") invoke lstrcat,addr directory,offset fd.cFileName ;добавляем к текущей папке имя найденной lea edx,directory push edx ;передаем это все в рекурсию call findAll jmp FNDNext .endif invoke lstrlen,offset fd.cFileName ;только так, sizeof дает размер всего буфера mov len1,eax push len1 ;длина имени файла передаем в функу push offset fd.cFileName ;адрес имени файла call GetExt ;поиск валидного расширения FNDNext: ;сюда переходим для поиска дальше invoke FindNextFile,hFindFile,offset fd cmp eax,0 ;файлы кончились, je ende1 ;идем на выход .if fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ;если это папка invoke lstrcmp,addr fd.cFileName,chr$(".") ;это "."? идем дальше test eax,eax jz FNDNext invoke lstrcmp,addr fd.cFileName,chr$("..") ;это ".."? также пропускаем test eax,eax jz FNDNext invoke lstrcat,addr directory,chr$("\") invoke lstrcat,addr directory,offset fd.cFileName ;добавляем к текущей папке имя найденной lea edx,directory push edx ;передаем это все в рекурсию call findAll jmp Skip ;возврат с функции и переход к новому значению .endif ;файл системный или скрытый? они не нужны явно test fd.dwFileAttributes,FILE_ATTRIBUTE_SYSTEM or FILE_ATTRIBUTE_HIDDEN jne Skip ;lea edx,directory ;для отладки вывод имени папки ;push edx ;передается в стек имя папки ;если попали сюда, значит не папка invoke lstrlen,offset fd.cFileName mov len1,eax push len1 push offset fd.cFileName call GetExt ;add esp,4 ;выравнять стек, если передаем папку Skip: ;сюда переходят, если была папка invoke RtlZeroMemory,addr buf,sizeof buf ;очищаем буфер invoke lstrcpy,addr directory,addr directoryRes ;восстановить из резервной копии jmp FNDNext ;цикл пока не кончатся файлы ende1: invoke FindClose,hFindFile ret findAll ENDP GetExt proc uses ecx ebx edx edi esi p2fname:dword,fnamesize:dword ;принимает указатель на имя файла и размер имени файла в байтах. local b2w:dword ;bytes to write mov ecx,fnamesize mov esi,p2fname add esi,ecx ;добавить размер,ибо чтение идет с конца sub esi,2 ;минус начальный адрес и нуллбайт std ;ищет расширение файла c конца parse_ext: ;search extension lodsb cmp al,'.' je get_ext loop parse_ext cld jmp @ret ;ecx = 0 && no matches in filename get_ext: ;detect extension add esi,2 ;чтобы указывало точно на расширение (1 буква + точка) cld mov ecx,extnum ;к-тво элементов в цикле xor edi,edi ;смещение относительно начала массива двордов searchExt: push ecx ;схороняем, ибо функция меняет его invoke lstrcmpi,esi,[pext1+edi] ;сравнить текущее расширение pop ecx .if eax==0 ;если совпало lea ebx,[cext1+edi] ;увеличить счетчик этого расширения inc dword ptr[ebx] mov edx,esi cmp edi,0 ;if jpg? write to file jnz @ret ;лог найденных файлов, пока убрал ; invoke CreateFile,chr$("log.txt"),FILE_APPEND_DATA,FILE_SHARE_WRITE or FILE_SHARE_READ,0,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,0 ; mov hFile,eax ; invoke lstrlen,[ebp+16] ;тут имя папки ; mov ebx,eax ; invoke WriteFile,hFile,[ebp+16],ebx,addr b2w,0 ;имя папки ; invoke WriteFile,hFile,chr$("\"),1h,addr b2w,0 ;пробел ; invoke WriteFile,hFile,p2fname,fnamesize,addr b2w,0 ;имя фаела ; invoke WriteFile,hFile,chr$(13,10),2h,addr b2w,0 ;перевод строки ; invoke CloseHandle,hFile ; invoke WriteString ; invoke StdOut,chr$(32,32,32) ; invoke StdOut,[pext1+edi] ; invoke StdOut,chr$(32,32,32) ; invoke StdOut,p2fname ; invoke Crlf jmp @ret .endif add edi,4 dec ecx jnz searchExt @ret: ret GetExt endp end Start