flat assembler
Message board for the users of flat assembler.

Index > Windows > problem with FindFirstFileW

Author
Thread Post new topic Reply to topic
marcinzabrze12



Joined: 07 Aug 2011
Posts: 60
marcinzabrze12
What is wrong in this code :
Code:
format pe gui 4.0
entry start
include 'win32ax.inc'
section '.data' data readable writeable

   filename         db '\\?\c:\*',0
   wfd              WIN32_FIND_DATA




section '.code' code readable executable
start:

        invoke  FindFirstFileW, filename, wfd
        .if eax = INVALID_HANDLE_VALUE
            invoke  MessageBox, 0,' error ','no data in wfd ',0
            jmp     endstart
        .endif
        invoke  MessageBox,0,wfd.cFileName, ' success ', 0
     endstart:
        invoke  ExitProcess,0






section '.idata' import data readable
library kernel32,'kernel32.dll',user32,'user32.dll'
include 'api\kernel32.inc'
include 'api\user32.inc'      
    
Post 26 Sep 2011, 08:57
View user's profile Send private message Reply with quote
Picnic



Joined: 05 May 2007
Posts: 1288
Location: Paradise Falls
Picnic
Hi,
I think you have to change these lines

Code:

include 'win32wx.inc'

...

filename         du '\\?\c:\*',0

    
Post 26 Sep 2011, 09:08
View user's profile Send private message Reply with quote
marcinzabrze12



Joined: 07 Aug 2011
Posts: 60
marcinzabrze12
Ok. Now it work corectly. thanks.
Post 26 Sep 2011, 19:40
View user's profile Send private message Reply with quote
typedef



Joined: 25 Jul 2010
Posts: 2913
Location: 0x77760000
typedef
Picnic wrote:
Hi,
I think you have to change these lines

Code:

include 'win32wx.inc'

...

filename         du '\\?\c:\*',0

    


But you didn't tell him the reason why he had to change it.

NOTE:
APIs ending with W are UNICODE therefore you must declare your string variables as DU(Define Unicode).
Post 26 Sep 2011, 23:27
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7796
Location: Kraków, Poland
Tomasz Grysztar
Do it like this:
Code:
format pe gui 4.0
entry start 
include 'win32wx.inc'
section '.data' data readable writeable 

   filename         TCHAR '\\?\c:\*',0
   wfd              WIN32_FIND_DATA 

section '.code' code readable executable 
start: 

        invoke  FindFirstFile, filename, wfd
        .if eax = INVALID_HANDLE_VALUE 
            invoke  MessageBox, 0,' error ','no data in wfd ',0 
            jmp     endstart 
        .endif 
        invoke  MessageBox,0,wfd.cFileName, ' success ', 0 
     endstart: 
        invoke  ExitProcess,0

section '.idata' import data readable
library kernel32,'kernel32.dll',user32,'user32.dll' 
include 'api\kernel32.inc' 
include 'api\user32.inc'    
and now you can switch between A and W versions by simply changing the include line.
Post 26 Sep 2011, 23:56
View user's profile Send private message Visit poster's website Reply with quote
typedef



Joined: 25 Jul 2010
Posts: 2913
Location: 0x77760000
typedef
^^Hmm, I didn't know there was win32wx.inc Very Happy

I assumed we had to hard code UNICODE. Cool
Post 27 Sep 2011, 00:19
View user's profile Send private message Reply with quote
marcinzabrze12



Joined: 07 Aug 2011
Posts: 60
marcinzabrze12
OK. I understand it but one more question :
TCHAR - define string bytes for 'win32a.inc' and string unicode for 'win32w.inc' - is that true ?
Post 27 Sep 2011, 15:13
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 3043
Location: vpcmipstrm
bitRAKE
True, TCHAR creates the corresponding string data for both ASCII and Unicode.
Post 27 Sep 2011, 16:00
View user's profile Send private message Visit poster's website Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1419
Location: Toronto, Canada
AsmGuru62
Of course, using CHARs will slow down the code - you are aware of this, right?
Post 27 Sep 2011, 16:15
View user's profile Send private message Send e-mail Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
AsmGuru62, what do you mean? Using CHARs compared to what is slower?
Post 27 Sep 2011, 17:17
View user's profile Send private message Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1419
Location: Toronto, Canada
AsmGuru62
Compared to WCHARS. The OS core works only with WCHARS, so all the functions like xxxA will first convert the ASCII text into UNICODE and then will call xxxW. So, directly using xxxW will be faster.
Post 28 Sep 2011, 15:03
View user's profile Send private message Send e-mail Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3170
Location: Denmark
f0dder
AsmGuru62 wrote:
Compared to WCHARS. The OS core works only with WCHARS, so all the functions like xxxA will first convert the ASCII text into UNICODE and then will call xxxW. So, directly using xxxW will be faster.
You'll be hard pressed to notice a speed difference.

The reason for using *W should be supporting non-english locales, not some silly notion of speed.

_________________
Image - carpe noctem
Post 28 Sep 2011, 19:05
View user's profile Send private message Visit poster's website Reply with quote
marcinzabrze12



Joined: 07 Aug 2011
Posts: 60
marcinzabrze12
fOldder:
Quote:

The reason for using *W should be supporting non-english locales, not some silly notion of speed.


msdn says that if i use unicode version of FindFirstFile* then i extend limit MAX_PATH - thats the reason why i iterested it. CreateFile function requires unicode version too for extend this limit.

I try to change function which search disk (recursive) that it will able to search a path's longer than MAX_PATH.

This is a code: (at now describes is non english yet i will change it)

Code:
format PE GUI 4.0 DLL
entry DllEntryPoint

include 'win32ax.inc'
section '.data' data readable writeable shareable

; Dane dla procedury ScanFolder:
        PathBuffer                 db MAX_PATH dup ?
        hSearchA                   dd ?


;       wskazniki referencyjne:
        cFileName                  dd ?




section '.text' code readable executable

proc DllEntryPoint hinstDLL,fdwReason,lpvReserved
        mov     eax,TRUE
        ret
endp


; VOID ScanTree (LPSTR startdirectory, LPSTR name_filter, LPWIN32_FIND_DATA winfind, PROC_ADDRESS proced);
proc  ScanTree stdcall, startdirectory, name_filter,  winfind,  proced
locals
          handle        dd ?
          path          db MAX_PATH dup ?
endl
macro Service
{
          lea           ebx, [path]
          mov           eax, [winfind]
          add           eax, WIN32_FIND_DATA.cFileName
          cinvoke       wsprintf, ebx, '%hs\%hs', [startdirectory], eax
          stdcall       ScanTree, ebx, [name_filter], [winfind], [proced]
}
          stdcall       ScanFolder, [startdirectory], [name_filter], [winfind], [proced]
          lea           ebx, [path]
          cinvoke       wsprintf, ebx, '%hs\*', [startdirectory]
          invoke        FindFirstFile, ebx, [winfind]
          cmp           eax, INVALID_HANDLE_VALUE
          je            .the_end
          mov           [handle], eax
          stdcall       IsSubdir, [winfind]
          test          eax, eax
          jnz           .find_next
          Service

      .find_next:
          invoke       FindNextFile, [handle], [winfind]
          test         eax, eax
          jz           @f
          stdcall      IsSubdir, [winfind]
          test         eax, eax
          jnz          .find_next
          Service
          jmp          .find_next

      @@:
          invoke       FindClose, [handle]

.the_end:
        ret
endp




; ..................................................................................................
; INT ScanFolder (LPSTR folder, LPSTR name_filter, LPWIN32_FIND_DATA winfind, PROC_ADDRESS proced);
;
; opis:       Przeszukuje podany katalog w poszukiwaniu plikow o pasujacych nazwach. Jezeli trafi na
;             pasujaca nazwe wykonuje dla niej procedure ktorej adres jest podany w czwartym parametrze.
;             Jezeli podana procedura zwraca zero - funkcja wyszukuje dalej, Jezeli procedura ta zwroci
;             wartosc <> zero wtedy ScanFolder natychmiast konczy swoje dzialanie.
;
; return:
;       00    = przeszukano caly katalog
;   <>  00    = zatrzymano przez funkcje [proced]
;
; ..................................................................................................
proc ScanFolder  stdcall,  folder,  name_filter,  winfind,  proced
macro FileService
{
        invoke    lstrcmp, [cFileName], '.'
        test      eax, eax
        jz        .find_next
        invoke    lstrcmp, [cFileName], '..'
        test      eax, eax
        jz        .find_next



        cinvoke   wsprintf, PathBuffer, '%hs\%hs', [folder], [cFileName]
        stdcall   [proced]

        test      eax, eax
        jnz       .end_stop
}

.ustawianie_wskaznikow:
        mov       ebx, [winfind]
        add       ebx, WIN32_FIND_DATA.cFileName
        mov       [cFileName], ebx

.start:
        cinvoke   wsprintf, PathBuffer, '%hs\%hs', [folder], [name_filter]
        invoke    FindFirstFile, PathBuffer, [winfind]
        cmp       eax, INVALID_HANDLE_VALUE
        je        .end_first
        mov       [hSearchA], eax

        FileService
     .find_next:
        invoke    FindNextFile, [hSearchA], [winfind]
        test      eax, eax
        jz        .end_next
        FileService
        jmp       .find_next

.end_stop:
        inc       eax
        ret

.end_next:
        invoke    FindClose, [hSearchA]
.end_first:

        ret
endp




; &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
; FUNKCJA: IsSubdir   WFD
;
; OPIS:
;       Sprawdz czy element znajdujacy sie we wskazanej
;       strukturze WIN32_FIND_DATA jest katalogiem.
;       Jezeli tak to czy jego nazwe nale|y pominac
;       podczas przeszukiwania. - nazwy '.' oraz '..'
;
; ARGUMENTY:
;       WFD     - Pointer na strukture WIN32_FIND_DATA
;
; RETURN:
;       00      - katalog
;       01      - niekatalog (lub nazwa pomijana)
;
; &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
proc IsSubdir uses ebx esi edi ebp, WFD:DWORD
pushfd
locals
        name1         db '.',0
        name2         db '..',0
endl
macro IgnoreName name
{
        lea     eax, name
        invoke  lstrcmp, ebx, eax
        test    eax, eax
        jz      .end_nie_katalog
}

;       sprawdzanie czy element w [WFD] jest katalogiem:
        mov     ebx, [WFD]
        bt      dword [ebx], 4
        jnc     .end_nie_katalog
;       sprawdzanie czy ignorowac nazwe elementu w [WFD]
        mov     ebx, [WFD]
        add     ebx, 44 ; pointer nazwy elementu do EBX

        IgnoreName      [name1]
        IgnoreName      [name2]


.end_katalog:
        xor     eax, eax
        popfd
        ret
.end_nie_katalog:
        mov     eax, 01
        popfd
        ret
endp; &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&




section '.idata' import data readable writeable

  library kernel32,'KERNEL32.DLL',\
          user32,'USER32.DLL'

include 'api\kernel32.inc'
include 'api\user32.inc'

section '.edata' export data readable
  export 'FindFile.dll',\
         ScanFolder,        'ScanFolder',\
         PathBuffer,        'PathBuffer',\
         ScanTree,          'ScanTree'

section '.reloc' fixups data discardable   
    


And here is a example of used it:
Code:
format pe gui 4.0
entry start
include 'win32ax.inc'
section '.data' data readable writeable shareable

   startpath        db '\\?\d:',0
   name             db '*',0
   wfd              WIN32_FIND_DATA

   counter          dd 0
   buf              db 100 dup ?

   pathbuf          db 32000 dup ?


section '.code' code readable executable
start:
        invoke  ScanTree, startpath, name, wfd, service
        cinvoke wsprintf, buf, '%d', [counter]
        invoke  MessageBox, 0, buf, 'liczba plikow na dysku c: ', 0
        invoke  ExitProcess,0



proc service stdcall
     inc       [counter]
     invoke    MessageBox, 0, [PathBuffer], 'Znaleziony element :', 0
     xor       eax, eax
     ret
endp


section '.idata' import data readable
library kernel32,'kernel32.dll',user32,'user32.dll',FindFile,'FindFile.dll'
include 'api\kernel32.inc'
include 'api\user32.inc'
import  FindFile,\
        ScanFolder,     'ScanFolder',\
        PathBuffer,     'PathBuffer',\
        ScanTree,       'ScanTree'   
    



All it work good bat only if on a disk isn't path longer than MAX_PATH
Post 01 Oct 2011, 16:22
View user's profile Send private message Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3170
Location: Denmark
f0dder
Your DLL still includes the ansi, not unicode, includes... you define your PathBuffer as MAX_PATH length (and it's a global variable, reaaaaally bad idea for a reusable piece of code). After seeing that, I stopped looking for other flaws Smile

PS: going longer than MAX_PATH is something you shouldn't do apart from really special needs - a huge amount of software (include Windows' Explorer) simply cannot handle anything larger than MAX_PATH. A shame, really.
Post 02 Oct 2011, 19:17
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.