Need for an DirectoryLister?(Mac+Windows) Win Support 256c+

Everything else that doesn't fall into one of the other PB categories.
GenRabbit
Enthusiast
Enthusiast
Posts: 118
Joined: Wed Dec 31, 2014 5:41 pm

Need for an DirectoryLister?(Mac+Windows) Win Support 256c+

Post by GenRabbit »

Here is a ProgramModule that lets you build a list of all files and folders from set directory;
Target was to get it fast, and modular. And to reduce the amount of code needed by using macros whenever there was code to spare
What it brings to the table
- Works on Mac, Linux and Windows
- Modular. You can easily add and remove functions you need
- Fast
- Windows: handles files+Folders with length up 32767 chars
- Windows: Uses WINAPI to get highest possible speed.
- Pattern search. Example "*.doc". Windows only
Hope you guys like it, and please tell me if there's a bug.

What I hope to add at a later time.
Search based on patterns.(MAC/Linux)

Description and code in Post below
Last edited by GenRabbit on Thu Jan 18, 2018 2:46 am, edited 3 times in total.
GenRabbit
Enthusiast
Enthusiast
Posts: 118
Joined: Wed Dec 31, 2014 5:41 pm

Re: Need for an DirectoryLister?(Mac+Windows) Win Support 25

Post by GenRabbit »

A deeper description on what the different parts of the API is for and what is required for its use;

Code: Select all

    Structure DirectoryOperationsAPI
        *addresse
        Options.w
        FileDataBlockSizeAdd.i
        Size.i
        Files.i
        Folders.i
        Total.i
    EndStructure
*Addresse / IN
Pointer/Integer
The addresse of the allocated memory which to write the result into. If not set will return with and error equal to (DirectoryOperations::#ERRMSG_MEMORY_NOT_ALLOCATED)
Advisable : Use 1MB (DirectoryOperations::#MemoryBlockSizeStart)

Options / IN
Word
Set this with the flag(s) needed. See below *1*

FileDataBlockSizeAdd / IN
Integer
Optional: If the allocated buffer runs out of memory, this will be added to the buffers size. If not set, the function will allocate the exact amount of memory it needs. This might slow it down.
Advisable. Use 1MB (DirectoryOperations::#MemoryBlockSizeAdd)

Size / OUT
Integer
Returns the total size of memory used for the files or folders names used. Size is in bytes.
Note: This can be smaller than the amount allocated because if the whole memory allocated aren't used it will remove overhead before returning.

Files / OUT
Integer
Returns the number of files found. These are counted even if not specified

Folders / OUT
Integer
Returns the number of folders found. These are counted even if not specified

Total / OUT
Integer
Returns the number of folders and files found in the allocated memory. Useful if you need to add them afterwards to an array Example: Dim.s Mylines(Total - 1)

A quick howto to get it to work;

Code: Select all

    ;*****************************************
    ; Define variables to use
    ;*****************************************
    Define.i ErrorMessage

    ;*****************************************
    ; Path to start from
    ;*****************************************
    RootFolder = "path to your folder\"                                          ; Must include \ (Windows) or / (Mac/Linux) in the end of the path

    ;*****************************************
    ; Prepare an API structure
    ;*****************************************
    Define.DirectoryOperations::DirectoryOperationsAPI API

    ;*****************************************
    ; Allocate memory, set Allocated memory size increase value, and Flags in the options(Optional)
    ;*****************************************
    API\addresse = AllocateMemory(DirectoryOperations::#MemoryBlockSizeStart)    ; allocate memory for Filenames and folder names.
    API\FileDataBlockSizeAdd = DirectoryOperations::#MemoryBlockSizeAdd             ; Optional.
    API\Options = DirectoryOperations::#FD_RECURSE                                         ; See Flags Below for options

    ;*****************************************
    ; Lets get started
    ;*****************************************
    ErrorMessage = DirectoryOperations::FileDirectory(RootFolder, "", @fd)
    ; Everything good?
    if ErrorMessage
        ; Check errormsg.
        ; See *1* Below
    else
        ; Insert your code here
    endif
    ; And free up the memory
    FreeMemory(API\addresse)                                                 ; When memory is no more needed.
Its very important that you free up the memory when you don't need the data in the buffer anymore

Unlock Keys
All
#MODULE_DATEACCESSED
- Unlocks the macros Macro_DateAccessed/Macro_DateAccessed_Seperator
#MODULE_DATEMODIFIED
- Unlocks the macros Macro_DateModified/Macro_DateModified_Seperator
#MODULE_FILESIZE
- Unlocks the macros Macro_FileSize/Macro_FileSize_Seperator
Windows Only
#MODULE_DATECREATED
- Unlocks the macros Macro_DateCreated/Macro_DateCreated_Seperator
#MODULE_ATTRIBUTEHIDDEN
- Unlocks the macros Macro_Attributehidden/Macro_Attributehidden_Seperator
#MODULE_ATTRIBUTEARCHIVE
- Unlocks the macros Macro_AttributeArchive/Macro_AttributeArchive_Seperator
#MODULE_ATTRIBUTECOMPRESSED
- Unlocks the macros Macro_AttributeCompressed/Macro_AttributeCompressed_Seperator
#MODULE_ATTRIBUTENORMAL
- Unlocks the macros Macro_AttributeNormal/Macro_AttributeNormal_Seperator
#MODULE_ATTRIBUTEREADONLY
- Unlocks the macros Macro_AttributeReadOnly/Macro_AttributeReadOnly_Seperator
#MODULE_ATTRIBUTESYSTEM
- Unlocks the macros Macro_AttributeSystem/Macro_AttributeSystem_Seperator
#MODULE_ATTRIBUTEENCRYPTED
- Unlocks the macros Macro_AttributeEncrypted/Macro_AttributeEncrypted_Seperator
Mac & linux Only
#MODULE_ATTRIBUTELINK
- Unlocks the macros Macro_AttributeLink/Macro_AttributeLink_Seperator
#MODULE_ATTRIBUTEREADUSER
- Unlocks the macros Macro_AttributeReadUser/Macro_AttributeReadUser_Seperator
#MODULE_ATTRIBUTEWRITEUSER
- Unlocks the macros Macro_AttributeWriteUser/Macro_AttributeWriteUser_Seperator
#MODULE_ATTRIBUTEEXECUSER
- Unlocks the macros Macro_AttributeExecUser/Macro_AttributeExecUser_Seperator
#MODULE_ATTRIBUTEREADGROUP
- Unlocks the macros Macro_AttributeReadGroup/Macro_AttributeReadGroup_Seperator
#MODULE_ATTRIBUTEWRITEGROUP
- Unlocks the macros Macro_AttributeWriteGroup/Macro_AttributeWriteGroup_Seperator
#MODULE_ATTRIBUTEEXECGROUP
- Unlocks the macros Macro_AttributeExecGroup/Macro_AttributeExecGroup_Seperator
#MODULE_ATTRIBUTEREADALL
- Unlocks the macros Macro_AttributeReadAll/Macro_AttributeReadAll_Seperator
#MODULE_ATTRIBUTEWRITEALL
- Unlocks the macros Macro_AttributeWriteAll/Macro_AttributeWriteAll_Seperator
#MODULE_ATTRIBUTEEXECALL
- Unlocks the macros Macro_AttributeExecAll/Macro_AttributeExecAll_Seperator

*1*
ERROR messages
#ERRMSG_OUT_OF_MEMORY
- Program couldn't allocate memory.
#ERRMSG_MEMORY_NOT_ALLOCATED
- Memory for API aren't allocated
#ERRMSG_NO_PATH_SPECIFIED
- Folderpath aren't specified
#ERRMSG_NO_SUCH_PATH
- Illegal path

Note : To check the error messages use DirectoryOperations:: as prefix for access to errormessage values. Example DirectoryOperations::#ERRMSG_OUT_OF_MEMORY

*2*
FLAGS ALL
#FD_RECURSE
- Also add subfolders
#FD_FOLDERS
- Add folders only
#FD_FILES
- Add files only. Makes #FD_Fullpath obselete as it will ONLY return the names. No path.
#FD_FULLPATH
- Adds the fullpath to file/folder
#FD_FILESIZE
- Adds Filesize to filenames
#FD_FileSystemEncrypted
- File/Folder is encrypted
#FD_DATEMODIFIED
- Adds Date Modified to filename/Foldername
#FD_DATEACCESSED
- Adds date accessed to filename/Foldername
FLAGS WINDOWS ONLY
#FD_DATECREATED
- Date file was created. NOTE: Created can be newer than modified.
#FD_FileSystemHidden
- Attribute : hidden
#FD_FileSystemArchive
- Attribute : Archive
#FD_FileSystemCompressed
- Attribute : Compressed
#FD_FileSystemNormal
- Attribute : Normal
#FD_FileSystemReadOnly
- Attribute : ReadOnly
#FD_FileSystemSystem
- Attribute : System file
FLAGS MAC & LINUX ONLY
#FD_FileSystemLink
- Attribute : Link
#FD_FileSystemReadUser
- Attribute : ReadUser
#FD_FileSystemWriteUser
- Attribute : WriteUser
#FD_FileSystemExecUser
- Attribute : ExecUser
#FD_FileSystemReadGroup
- Attribute : ReadGroup
#FD_FileSystemWriteGroup
- Attribute : WriteGroup
#FD_FileSystemExecGroup
- Attribute : ExecGroup
#FD_FileSystemReadAll
- Attribute : ReadAll
#FD_FileSystemWriteAll
- Attribute : WriteAll
#FD_FileSystemExecAll
- Attribute : ExecAll

Note: Use of #FD_FILES will make the flag #FD_FULLPATH obsolete
Note 2: To get the attribute values from module use DirectoryOperations:: as prefix. Example DirectoryOperations::#FD_RECURSE

To get data out of buffer
Example 1: Using API\Total as end marker

Code: Select all

    x = 0
    If CreateFile(0,RootFolder + "Result.txt")
        For y = 1 to API\Total
            TempName = PeekS(API\addresse + x, -1, #PB_Unicode)
            TempLength = (Len(TempName) + 1) * DirectoryOperations::#Length_Char
            WriteStringN(0, TempName, #PB_Ascii)
            x + TempLength
        Next y
        CloseFile(0)
    EndIf
Example 2: Using API\Size as end marker

Code: Select all

    x = 0
    If CreateFile(0,RootFolder + "Result.txt")
        While fd\Size > x
            TempName = PeekS(API\addresse + x, -1, #PB_Unicode)
            TempLength = (Len(TempName) + 1) * DirectoryOperations::#Length_Char
            WriteStringN(0, TempName, #PB_Ascii)
            x + TempLength
        Wend
        CloseFile(0)
    EndIf
How to add Functions like Attributes..
All macros as the program stands now is turned of.

How to activate:
For this example, we will need the modifiy attribute. To get the code and Attribute settings we have to set the flags.
Change

Code: Select all

#EXTENDEDFILEDIRECTORY = 0
#MODULE_DATEMODIFIED = 0
to this

Code: Select all

#EXTENDEDFILEDIRECTORY = 1
#MODULE_DATEMODIFIED = 1
This will make these two macros and one flag available available.
Macrosd and Flag;
Macro_DateModified
Macro_DateModified_Seperator
#FD_DATEMODIFIED


If you use Macro_DateModified, you should call InsertSeperator just after to add your own seperator.
example

Code: Select all

Macro_DateModified
InsertSeperator " "
This will insert a space between the Datemodified and files or folder names following.
If a space is what you want to use, these to can be replaced with just Macro_DateModified_Seperator

Insert Functions(Macros) you want between these lines

Code: Select all

       ; Insert Macros Begin
       ; Insert Macros end
Example. for the above

Code: Select all

       ; Insert Macros Begin
       Macro_DateModified_Seperator
       ; Insert Macros end
You can also do it like this

Code: Select all

       ; Insert Macros Begin
       Macro_DateModified
       InsertSeperator #DATESEPERATOR$
       ; Insert Macros end


Main Program Code

Code: Select all

DeclareModule DirectoryOperations
    EnableExplicit
    #EXTENDEDFILEDIRECTORY = 0
    CompilerIf #EXTENDEDFILEDIRECTORY
            #MODULE_DATEACCESSED             = 0
            #MODULE_DATEMODIFIED             = 0
            #MODULE_FILESIZE                 = 0
        CompilerIf #PB_Compiler_OS = #PB_OS_Windows
            ; Windows Only
            #MODULE_DATECREATED              = 0
            #MODULE_ATTRIBUTEHIDDEN          = 0
            #MODULE_ATTRIBUTEARCHIVE         = 0
            #MODULE_ATTRIBUTECOMPRESSED      = 0
            #MODULE_ATTRIBUTENORMAL          = 0
            #MODULE_ATTRIBUTEREADONLY        = 0
            #MODULE_ATTRIBUTESYSTEM          = 0
            #MODULE_ATTRIBUTEENCRYPTED       = 0
        CompilerElse
            ; Mac & linux Only
            #MODULE_ATTRIBUTELINK            = 0
            #MODULE_ATTRIBUTEREADUSER        = 0
            #MODULE_ATTRIBUTEWRITEUSER       = 0
            #MODULE_ATTRIBUTEEXECUSER        = 0
            #MODULE_ATTRIBUTEREADGROUP       = 0
            #MODULE_ATTRIBUTEWRITEGROUP      = 0
            #MODULE_ATTRIBUTEEXECGROUP       = 0
            #MODULE_ATTRIBUTEREADALL         = 0
            #MODULE_ATTRIBUTEWRITEALL        = 0
            #MODULE_ATTRIBUTEEXECALL         = 0
        CompilerEndIf
    CompilerEndIf
    CompilerSelect #PB_Compiler_Processor
        CompilerCase #PB_Processor_x86
            #Length_Integer = 4
        CompilerCase #PB_Processor_x64
            #Length_Integer = 8
    CompilerEndSelect

    CompilerSelect #PB_Compiler_OS
        CompilerCase #PB_OS_Windows
            #FolderDelimiter$ = "\"
            #WINDOWS_DIRECTORY   = 16
        CompilerDefault
            #FolderDelimiter$ = "/"
    CompilerEndSelect

    CompilerIf #PB_Compiler_Unicode
        #Length_Char = 2
    CompilerElse
        #Length_Char = 1
    CompilerEndIf

    ;--- Optional Values for memory allocation
    #MemoryBlockSizeStart = 1024 * 1024 ; Allocated memory 1MB
    #MemoryBlockSizeAdd = 1024 * 1024   ; Allocated memory 1MB
    ;--- Error Flag
    Enumeration ERRMSG_ 10 Step 5
        #ERRMSG_OUT_OF_MEMORY
        #ERRMSG_MEMORY_NOT_ALLOCATED
        #ERRMSG_NO_PATH_SPECIFIED
        #ERRMSG_NO_SUCH_PATH
        #ERRMSG_NO_FILE_OR_FOLDER
    EndEnumeration

    ;--- Flags
        EnumerationBinary FD_
            #FD_RECURSE
            #FD_FOLDERS         ; Only Foldername
            #FD_FILES           ; Only Filename
            #FD_FULLPATH        ; Fullpath?
            #FD_FILESIZE        ; Filesize
            CompilerIf #MODULE_DATEMODIFIED
                #FD_DATEMODIFIED
            CompilerEndIf
            CompilerIf #MODULE_DATEACCESSED
                #FD_DATEACCESSED
            CompilerEndIf
            CompilerIf #PB_Compiler_OS = #PB_OS_Windows
                ; Window specific flags
                CompilerIf #MODULE_DATECREATED
                    #FD_DATECREATED
                CompilerEndIf

                CompilerIf #MODULE_ATTRIBUTEHIDDEN
                    #FD_FileSystemHidden
                CompilerEndIf
                CompilerIf #MODULE_ATTRIBUTEARCHIVE
                    #FD_FileSystemArchive
                CompilerEndIf
                CompilerIf #MODULE_ATTRIBUTECOMPRESSED
                    #FD_FileSystemCompressed
                CompilerEndIf
                CompilerIf #MODULE_ATTRIBUTEENCRYPTED
                    #FD_FileSystemEncrypted
                CompilerEndIf
                CompilerIf #MODULE_ATTRIBUTENORMAL
                    #FD_FileSystemNormal
                CompilerEndIf
                CompilerIf #MODULE_ATTRIBUTEREADONLY
                    #FD_FileSystemReadOnly
                CompilerEndIf
                CompilerIf #MODULE_ATTRIBUTESYSTEM
                    #FD_FileSystemSystem
                CompilerEndIf
            CompilerElse
                ; Mac/Linux specific flags
                CompilerIf #MODULE_ATTRIBUTELINK
                    #FD_FileSystemLink
                CompilerEndIf
                CompilerIf #MODULE_ATTRIBUTEREADUSER
                    #FD_FileSystemReadUser    ; Access flags For the owning user
                CompilerEndIf
                CompilerIf #MODULE_ATTRIBUTEWRITEUSER
                    #FD_FileSystemWriteUser
                CompilerEndIf
                CompilerIf #MODULE_ATTRIBUTEEXECUSER
                    #FD_FileSystemExecUser
                CompilerEndIf
                CompilerIf #MODULE_ATTRIBUTEREADGROUP
                    #FD_FileSystemReadGroup   ; Access flags for the owning user's group
                CompilerEndIf
                CompilerIf #MODULE_ATTRIBUTEWRITEGROUP
                    #FD_FileSystemWriteGroup
                CompilerEndIf
                CompilerIf #MODULE_ATTRIBUTEEXECGROUP
                    #FD_FileSystemExecGroup
                CompilerEndIf
                CompilerIf #MODULE_ATTRIBUTEREADALL
                    #FD_FileSystemReadAll     ; Access flags for all other users
                CompilerEndIf
                CompilerIf #MODULE_ATTRIBUTEWRITEALL
                    #FD_FileSystemWriteAll
                CompilerEndIf
                CompilerIf #MODULE_ATTRIBUTEEXECALL
                    #FD_FileSystemExecAll
                CompilerEndIf
            CompilerEndIf
        EndEnumeration

    CompilerIf #EXTENDEDFILEDIRECTORY
        #TIMEFORMAT$ = "%DD-%MM-%YYYY %HH:%II"
        #DATESEPERATOR$ = " "
        #ATTRIBUTESEPERATOR$ = " "
        #FILESIZESEPERATOR$ = " "
    CompilerEndIf
    ;--- Macro's begin
    CompilerIf #EXTENDEDFILEDIRECTORY
        Macro InsertSeperator
            eXtended +
        EndMacro
        Macro Macro_Attributes(FDFLAG, PBFLAG, RESULT1, RESULT2, SEPERATOR)
            If (*fd\Options) & FDFLAG
            CompilerIf #PB_Compiler_OS = #PB_OS_Windows
                If SearchData\dwFileAttributes & PBFLAG
                    eXtended + RESULT1 + SEPERATOR
                Else
                    eXtended + RESULT2 + SEPERATOR
                EndIf
            CompilerElse
                    If DirectoryEntryAttributes(Exadir) & PBFLAG
                        eXtended + RESULT1 + SEPERATOR
                    Else
                        eXtended + RESULT2 + SEPERATOR
                    EndIf
                EndIf
            CompilerEndIf
        EndMacro

        CompilerIf #MODULE_FILESIZE
            CompilerIf #PB_Compiler_OS = #PB_OS_Windows
                Macro Macro_FileSize
                    If (*fd\Options) & #FD_FILESIZE
                        eXtended + Str((SearchData\nFileSizeHigh * $100000000) + SearchData\nFileSizeLow)
                    EndIf
                EndMacro
                Macro Macro_FileSize_Seperator
                    If (*fd\Options) & #FD_FILESIZE
                        eXtended + Str((SearchData\nFileSizeHigh * $100000000) + SearchData\nFileSizeLow) + #FILESIZESEPERATOR$
                    EndIf
                EndMacro
            CompilerElse
                Macro Macro_FileSize
                    If (*fd\Options) & #FD_FILESIZE
                        eXtended + Str(DirectoryEntrySize(ExaDir))
                    EndIf
                EndMacro
                Macro Macro_FileSize_Seperator
                    If (*fd\Options) & #FD_FILESIZE
                        eXtended + Str(DirectoryEntrySize(ExaDir))+ #FILESIZESEPERATOR$
                    EndIf
                EndMacro
            CompilerEndIf
        CompilerEndIf

        CompilerIf #MODULE_DATEMODIFIED
            CompilerIf #PB_Compiler_OS = #PB_OS_Windows
                Macro Macro_DateModified
                    If (*fd\Options) & #FD_DATEMODIFIED
                        FileTime = SearchData\ftLastWriteTime
                        MACRO_DateAndTimeFormat
                        eXtended + FileDate
                   EndIf
                EndMacro
                Macro Macro_DateModified_Seperator
                    If (*fd\Options) & #FD_DATEMODIFIED
                        FileTime = SearchData\ftLastWriteTime
                        MACRO_DateAndTimeFormat
                        eXtended + FileDate + #DATESEPERATOR$
                   EndIf
                EndMacro
            CompilerElse
                Macro Macro_DateModified
                    If (*fd\Options) & #FD_DATEMODIFIED
                        eXtended + FormatDate(#TIMEFORMAT$, DirectoryEntryDate(Exadir , #PB_Date_Modified))
                    EndIf
                EndMacro
                Macro Macro_DateModified_Seperator
                    If (*fd\Options) & #FD_DATEMODIFIED
                        eXtended + FormatDate(#TIMEFORMAT$, DirectoryEntryDate(Exadir , #PB_Date_Modified)) + #DATESEPERATOR$
                    EndIf
                EndMacro
            CompilerEndIf
        CompilerEndIf

        CompilerIf #MODULE_DATEACCESSED
            CompilerIf #PB_Compiler_OS = #PB_OS_Windows
                Macro Macro_DateAccessed
                    If (*fd\Options) & #FD_DATEACCESSED
                        FileTime = SearchData\ftLastAccessTime
                        MACRO_DateAndTimeFormat
                        eXtended + FileDate
                    EndIf
                EndMacro
                Macro Macro_DateAccessed_Seperator
                    If (*fd\Options) & #FD_DATEACCESSED
                        FileTime = SearchData\ftLastAccessTime
                        MACRO_DateAndTimeFormat
                        eXtended + FileDate + #DATESEPERATOR$
                    EndIf
                EndMacro
            CompilerElse
                Macro Macro_DateAccessed
                    If (*fd\Options) & #FD_DATEACCESSED
                        eXtended + FormatDate(#TIMEFORMAT$, DirectoryEntryDate(Exadir , #PB_Date_Accessed))
                    EndIf
                EndMacro
                Macro Macro_DateAccessed_Seperator
                    If (*fd\Options) & #FD_DATEACCESSED
                        eXtended + FormatDate(#TIMEFORMAT$, DirectoryEntryDate(Exadir , #PB_Date_Accessed)) + #DATESEPERATOR$
                    EndIf
                EndMacro
            CompilerEndIf
        CompilerEndIf
        CompilerIf #PB_Compiler_OS = #PB_OS_Windows
            ; Windows Only
            CompilerIf #MODULE_DATECREATED
                Macro Macro_DateCreated
                    If (*fd\Options) & #FD_DATECREATED
                        FileTime = SearchData\ftCreationTime
                        MACRO_DateAndTimeFormat
                        eXtended + FileDate
                    EndIf
                EndMacro
                Macro Macro_DateCreated_Seperator
                    If (*fd\Options) & #FD_DATECREATED
                        FileTime = SearchData\ftCreationTime
                        MACRO_DateAndTimeFormat
                        eXtended + FileDate + #DATESEPERATOR$
                    EndIf
                EndMacro
            CompilerEndIf

            CompilerIf #MODULE_ATTRIBUTEHIDDEN
                Macro Macro_Attributehidden
                    Macro_Attributes(#FD_FileSystemHidden, #FILE_ATTRIBUTE_HIDDEN, "[Hidden]", "[]", "")
                EndMacro
                Macro Macro_Attributehidden_Seperator
                    Macro_Attributes(#FD_FileSystemHidden, #FILE_ATTRIBUTE_HIDDEN, "[Hidden]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf
            CompilerIf #MODULE_ATTRIBUTEENCRYPTED
                Macro Macro_AttributeEncrypted
                    Macro_Attributes(#FD_FileSystemEncrypted, #FILE_ATTRIBUTE_ENCRYPTED, "[ENCRYPTED]", "[]", "")
                EndMacro
                Macro Macro_AttributeEncrypted_Seperator
                    Macro_Attributes(#FD_FileSystemEncrypted, #FILE_ATTRIBUTE_ENCRYPTED, "[ENCRYPTED]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf

            CompilerIf #MODULE_ATTRIBUTEARCHIVE
                Macro Macro_AttributeArchive
                    Macro_Attributes(#FD_FileSystemHidden, #FILE_ATTRIBUTE_ARCHIVE, "[Archive]", "[]", "")
                EndMacro
                Macro Macro_AttributeArchive_Seperator
                    Macro_Attributes(#FD_FileSystemHidden, #FILE_ATTRIBUTE_ARCHIVE, "[Archive]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf

            CompilerIf #MODULE_ATTRIBUTECOMPRESSED
                Macro Macro_AttributeCompressed
                    Macro_Attributes(#FD_FileSystemCompressed, #FILE_ATTRIBUTE_COMPRESSED, "[Compressed]", "[]", "")
                EndMacro
                Macro Macro_AttributeCompressed_Seperator
                    Macro_Attributes(#FD_FileSystemCompressed, #FILE_ATTRIBUTE_COMPRESSED, "[Compressed]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf

            CompilerIf #MODULE_ATTRIBUTENORMAL
                Macro Macro_AttributeNormal
                    Macro_Attributes(#FD_FileSystemNormal, #FILE_ATTRIBUTE_NORMAL, "[Normal]", "[]", "")
                EndMacro
                Macro Macro_AttributeNormal_Seperator
                    Macro_Attributes(#FD_FileSystemNormal, #FILE_ATTRIBUTE_NORMAL, "[Normal]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf

            CompilerIf #MODULE_ATTRIBUTEREADONLY
                Macro Macro_AttributeReadOnly
                    Macro_Attributes(#FD_FileSystemReadOnly, #FILE_ATTRIBUTE_READONLY, "[Read Only]", "[]", "")
                EndMacro
                Macro Macro_AttributeReadOnly_Seperator
                    Macro_Attributes(#FD_FileSystemReadOnly, #FILE_ATTRIBUTE_READONLY, "[Read Only]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf

            CompilerIf #MODULE_ATTRIBUTESYSTEM
                Macro Macro_AttributeSystem
                    Macro_Attributes(#FD_FileSystemSystem, #FILE_ATTRIBUTE_SYSTEM, "[System File]", "[]", "")
                EndMacro
                Macro Macro_AttributeSystem_Seperator
                    Macro_Attributes(#FD_FileSystemSystem, #FILE_ATTRIBUTE_SYSTEM, "[System File]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf

        CompilerElse
        ; Mac/Linux Only
            CompilerIf #MODULE_ATTRIBUTELINK
                Macro Macro_AttributeLink
                    Macro_Attributes(#FD_FileSystemLink, #PB_FileSystem_Link, "[Link]", "[]", "")
                EndMacro
                Macro Macro_AttributeLink_Seperator
                    Macro_Attributes(#FD_FileSystemLink, #PB_FileSystem_Link, "[Link]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf

            CompilerIf #MODULE_ATTRIBUTEREADUSER
                Macro Macro_AttributeReadUser
                    Macro_Attributes(#FD_FileSystemReadUser, #PB_FileSystem_ReadUser, "[Owning User/Read]", "[]", "")
                EndMacro
                Macro Macro_AttributeReadUser_Seperator
                    Macro_Attributes(#FD_FileSystemReadUser, #PB_FileSystem_ReadUser, "[Owning User/Read]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf

            CompilerIf #MODULE_ATTRIBUTEWRITEUSER
                Macro Macro_AttributeWriteUser
                    Macro_Attributes(#FD_FileSystemWriteUser, #PB_FileSystem_WriteUser, "[Owning User/Write]", "[]", "")
                EndMacro
                Macro Macro_AttributeWriteUser_Seperator
                    Macro_Attributes(#FD_FileSystemWriteUser, #PB_FileSystem_WriteUser, "[Owning User/Write]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf

            CompilerIf #MODULE_ATTRIBUTEEXECUSER
                Macro Macro_AttributeExecUser
                    Macro_Attributes(#FD_FileSystemExecUser, #PB_FileSystem_ExecUser, "[Owning User/Execute]", "[]", "")
                EndMacro
                Macro Macro_AttributeExecUser_Seperator
                    Macro_Attributes(#FD_FileSystemExecUser, #PB_FileSystem_ExecUser, "[Owning User/Execute]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf

            CompilerIf #MODULE_ATTRIBUTEREADGROUP
                Macro Macro_AttributeReadGroup
                    Macro_Attributes(#FD_FileSystemReadGroup, #PB_FileSystem_ReadGroup, "[Owning User Group/Read]", "[]", "")
                EndMacro
                Macro Macro_AttributeReadGroup_Seperator
                    Macro_Attributes(#FD_FileSystemReadGroup, #PB_FileSystem_ReadGroup, "[Owning User Group/Read]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf

            CompilerIf #MODULE_ATTRIBUTEWRITEGROUP
                Macro Macro_AttributeWriteGroup
                    Macro_Attributes(#FD_FileSystemWriteGroup, #PB_FileSystem_WriteGroup, "[Owning User Group/Write]", "[]", "")
                EndMacro
                Macro Macro_AttributeWriteGroup_Seperator
                    Macro_Attributes(#FD_FileSystemWriteGroup, #PB_FileSystem_WriteGroup, "[Owning User Group/Write]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf

            CompilerIf #MODULE_ATTRIBUTEEXECGROUP
                Macro Macro_AttributeExecGroup
                    Macro_Attributes(#FD_FileSystemExecGroup, #PB_FileSystem_ExecGroup, "[Owning User Group/Exec]", "[]", "")
                EndMacro
                Macro Macro_AttributeExecGroup_Seperator
                    Macro_Attributes(#FD_FileSystemExecGroup, #PB_FileSystem_ExecGroup, "[Owning User Group/Exec]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf

            CompilerIf #MODULE_ATTRIBUTEREADALL
                Macro Macro_AttributeReadAll
                    Macro_Attributes(#FD_FileSystemReadAll, #PB_FileSystem_ReadAll, "[All Other Users/Read]", "[]", "")
                EndMacro
                Macro Macro_AttributeReadAll_Seperator
                    Macro_Attributes(#FD_FileSystemReadAll, #PB_FileSystem_ReadAll, "[All Other Users/Read]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf

            CompilerIf #MODULE_ATTRIBUTEWRITEALL
                Macro Macro_AttributeWriteAll
                    Macro_Attributes(#FD_FileSystemWriteAll, #PB_FileSystem_WriteAll, "[All Other Users/Write]", "[]", "")
                EndMacro
                Macro Macro_AttributeWriteAll_Seperator
                    Macro_Attributes(#FD_FileSystemWriteAll, #PB_FileSystem_WriteAll, "[All Other Users/Write]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf

            CompilerIf #MODULE_ATTRIBUTEEXECALL
                Macro Macro_AttributeExecAll
                    Macro_Attributes(#FD_FileSystemExecAll, #PB_FileSystem_ExecAll, "[All Other Users/Execute]", "[]", "")
                EndMacro
                Macro Macro_AttributeExecAll_Seperator
                    Macro_Attributes(#FD_FileSystemExecAll, #PB_FileSystem_ExecAll, "[All Other Users/Execute]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf
        CompilerEndIf

        Macro MACRO_DateAndTimeFormat
            FileTimeToLocalFileTime_(@FileTime, @NewFileTime)
            FileTimeToSystemTime_(@NewFileTime,@SYSTEMTIME)
            FileDate = ReplaceString(#TIMEFORMAT$,"%YYYY",Str(SystemTime\wYear), #PB_String_NoCase) ; Year (1601 - 30827)
            FileDate = ReplaceString(FileDate,"%MM",Right("0" + Str(SystemTime\wMonth),2),#PB_String_NoCase) ; Month (1-12)
            FileDate = ReplaceString(FileDate,"%DD",Right("0" + Str(SystemTime\wDay),2),#PB_String_NoCase) ; Day(1-31)
            FileDate = ReplaceString(FileDate,"%HH",Right("0" + Str(SystemTime\wHour),2),#PB_String_NoCase); Hour(0-23)
            FileDate = ReplaceString(FileDate,"%II",Right("0" + Str(SystemTime\wMinute),2),#PB_String_NoCase); Minute(0-59)
            FileDate = ReplaceString(FileDate,"%SS",Right("0" + Str(SystemTime\wSecond),2),#PB_String_NoCase); Minute(0-59)
        EndMacro

        Macro Macro_ExtendedDirectory
            ; Macros Begin
            ;macro_FileSize_Seperator
            Macro_DateCreated_Seperator
            ; Macros End
        EndMacro

    CompilerEndIf
    ;--- Macro's END

    ;--- Structure
    Structure DirectoryOperationsAPI
        *addresse
        Options.w
        FileDataBlockSizeAdd.i
        Size.i
        Files.i
        Folders.i
        Total.i
    EndStructure
    Declare FileDirectory(RootFolder.s, pattern.s, *fd.DirectoryOperationsAPI)
EndDeclareModule

Module DirectoryOperations
    Global.i FileDataBlockSize
    Procedure.i StoreResult(FilePathOrFilename.s, *Fd.DirectoryOperationsAPI)
        Protected *PathMapNew
        Protected.i LengthToAdd
        Protected.i TempLength = (Len(FilePathOrFilename) + 1) * #Length_Char
        If (*Fd\Size + TempLength) >= FileDataBlockSize
            ; To small block. Time to increase
            If *Fd\FileDataBlockSizeAdd > TempLength
                LengthToAdd = *Fd\FileDataBlockSizeAdd
            Else
                LengthToAdd = TempLength
            EndIf

            *PathMapNew = ReAllocateMemory(*Fd\addresse, FileDataBlockSize + LengthToAdd)
            If *PathMapNew
                *Fd\addresse = *PathMapNew
                FileDataBlockSize + LengthToAdd
            Else
                ProcedureReturn #ERRMSG_OUT_OF_MEMORY
            EndIf
        EndIf
        PokeS(*Fd\addresse + *Fd\Size,FilePathOrFilename)
        *Fd\Total + 1
        *Fd\Size + TempLength
        ProcedureReturn 0
    EndProcedure

    Procedure.i RecurseDir(RootFolder.s, PresentRoot.s, Pattern.s, *Fd.DirectoryOperationsAPI)
        Protected.i ExaDir
        Protected.i *PathMapNew
        Protected.s TempName
        Protected.i ForcedQuit
        CompilerIf #EXTENDEDFILEDIRECTORY
            Protected.s eXtended
        CompilerEndIf
        CompilerIf #PB_Compiler_OS = #PB_OS_Windows
            Protected.WIN32_FIND_DATA SearchData
            Protected.SYSTEMTIME SystemTime
            Protected.Filetime FileTime, NewFileTime
            Protected.s FileDate
            Protected.i ErrorValue
            ; // ***************************
            ; // Windows
            ; // ***************************
            ExaDir = FindFirstFile_(rootFolder + "*", SearchData)

            If ExaDir
                While FindNextFile_(ExaDir, SearchData)
                    CompilerIf #EXTENDEDFILEDIRECTORY
                        ; Inserts all Attributes/Filehandler macros we have added.
                        Macro_ExtendedDirectory
                    CompilerEndIf
                    TempName = PeekS(@SearchData\cFileName)
                    If SearchData\dwFileAttributes & #WINDOWS_DIRECTORY
                        ;--- Folder
                        ;TempName = PeekS(@SearchData\cFileName)
                        If (TempName <> ".") And (TempName <> "..")
                            *Fd\Folders + 1
                            If (*Fd\Options & #FD_RECURSE)
                                ForcedQuit = RecurseDir(RootFolder + TempName + #FolderDelimiter$, PresentRoot + TempName + #FolderDelimiter$, Pattern, *Fd)
                                If ForcedQuit
                                    Break
                                EndIf
                            EndIf
                            If *Fd\Options & #FD_FOLDERS
                                ForcedQuit = StoreResult(PresentRoot + TempName + #FolderDelimiter$, *Fd)
                            EndIf
                            If ForcedQuit
                                Break
                            EndIf
                        EndIf
                    ;--- File
                    Else
                        ;TempName = DirectoryEntryName(ExaDir)
                        *Fd\Files + 1
                        If *Fd\Options & #FD_FILES
                            CompilerIf #EXTENDEDFILEDIRECTORY
                                ForcedQuit = StoreResult(eXtended + TempName, *Fd)
                            CompilerElse
                                ForcedQuit = StoreResult(TempName, *Fd)
                            CompilerEndIf
                        ElseIf Not *Fd\Options & #FD_FOLDERS
                            CompilerIf #EXTENDEDFILEDIRECTORY
                                ForcedQuit = StoreResult(eXtended + PresentRoot + TempName, *Fd)
                            CompilerElse
                                ForcedQuit = StoreResult(PresentRoot + TempName, *Fd)
                            CompilerEndIf
                        EndIf
                    EndIf
                    If ForcedQuit
                        Break
                    EndIf
                    eXtended = ""
                Wend
                FindClose_(ExaDir)
            Else
                ProcedureReturn #ERRMSG_NO_SUCH_PATH
            EndIf
            ProcedureReturn ForcedQuit

        CompilerElse
            ; // ***************************
            ; // Mac & Linux
            ; // ***************************
            ExaDir = ExamineDirectory(#PB_Any, RootFolder, Pattern)
            If ExaDir
                While NextDirectoryEntry(ExaDir)
                    CompilerIf #EXTENDEDFILEDIRECTORY
                        ; Inserts all Attributes/Filehandler macros we have added.
                        ExtendedDirectoryMacros
                    CompilerEndIf
                    Select DirectoryEntryType(ExaDir)
                        ;--- Folder
                        Case #PB_DirectoryEntry_Directory
                            TempName = DirectoryEntryName(ExaDir)
                            If (TempName <> ".") And (TempName <> "..")
                                *Fd\Folders + 1
                                If (*Fd\Options & #FD_RECURSE)
                                    ForcedQuit = RecurseDir(RootFolder + TempName + #FolderDelimiter$, PresentRoot + TempName + #FolderDelimiter$, *Fd)
                                    If ForcedQuit
                                        Break
                                    EndIf
                                EndIf
                                If *Fd\Options & #FD_FOLDERS
                                    ForcedQuit = StoreResult(PresentRoot + TempName + #FolderDelimiter$, *Fd)
                                EndIf
                                If ForcedQuit
                                    Break
                                EndIf
                            EndIf
                        ;--- File
                        Case #PB_DirectoryEntry_File
                            TempName = DirectoryEntryName(ExaDir)
                            *Fd\Files + 1
                            If *Fd\Options & #FD_FILES
                                CompilerIf #EXTENDEDFILEDIRECTORY
                                    ForcedQuit = StoreResult(eXtended + TempName, *Fd)
                                CompilerElse
                                    ForcedQuit = StoreResult(TempName, *Fd)
                                CompilerEndIf
                            ElseIf Not *Fd\Options & #FD_FOLDERS
                                CompilerIf #EXTENDEDFILEDIRECTORY
                                    ForcedQuit = StoreResult(eXtended + PresentRoot + TempName, *Fd)
                                CompilerElse
                                    ForcedQuit = StoreResult(PresentRoot + TempName, *Fd)
                                CompilerEndIf
                            EndIf
                    EndSelect
                    If ForcedQuit
                        Break
                    EndIf
                    eXtended = ""
                Wend
                FinishDirectory(ExaDir)
            Else
                ProcedureReturn #ERRMSG_NO_SUCH_PATH
            EndIf
            ProcedureReturn ForcedQuit
        CompilerEndIf
    EndProcedure
    Procedure.i FileDirectory(RootFolder.s, Pattern.s, *fd.DirectoryOperationsAPI)
        ; Initialize values
        Protected.s subfolder
        Protected.i Result
        Protected *OptimizedBlockSize
        CompilerIf #PB_Compiler_OS = #PB_OS_Windows And #PB_Compiler_Processor = #PB_Processor_x86
            Protected.i Redirection
        CompilerEndIf
        If *fd\addresse
            *fd\Files = 0
            *fd\Folders = 0
            *fd\Size = 0
            *fd\Total = 0
            FileDataBlockSize = MemorySize(*fd\addresse) ; Sets \FileDataBlocksize to the Size of the Allocated buffer.
            If *fd\Options & #FD_FULLPATH
                SubFolder = RootFolder
            EndIf
            If Right(RootFolder,1) <> #FolderDelimiter$
                RootFolder + #FolderDelimiter$
                Result = SetCurrentDirectory_(@RootFolder)
            Else
                Result = SetCurrentDirectory_(@RootFolder)
            EndIf
            If result
                CompilerIf #PB_Compiler_OS = #PB_OS_Windows And #PB_Compiler_Processor = #PB_Processor_x86
                    Wow64DisableWow64FsRedirection_(@Redirection)
                    Result = RecurseDir(RootFolder, SubFolder ,Pattern, *fd)
                    Wow64RevertWow64FsRedirection_(Redirection)
                CompilerElse
                    Result = RecurseDir(RootFolder, SubFolder ,Pattern, *fd)
                CompilerEndIf
                If Not Result
                    If *fd\Size
                        If FileDataBlockSize > *fd\Size
                            *OptimizedBlockSize = ReAllocateMemory(*Fd\addresse, *fd\Size)
                            If *OptimizedBlockSize
                                *Fd\addresse = *OptimizedBlockSize
                            Else
                                ProcedureReturn #ERRMSG_OUT_OF_MEMORY
                            EndIf
                        EndIf
                    Else
                        ProcedureReturn #ERRMSG_NO_FILE_OR_FOLDER
                    EndIf
                EndIf
            Else
                ProcedureReturn #ERRMSG_NO_SUCH_PATH
            EndIf
        Else
            ProcedureReturn #ERRMSG_MEMORY_NOT_ALLOCATED
        EndIf
    EndProcedure
EndModule
Test Code

Code: Select all

;-- Program starts
EnableExplicit
;--- local Global Strings variables
Define fd.DirectoryOperations::DirectoryOperationsAPI
; Strings
Define.s RootFolder
RootFolder = "\\?\F:\Projects\Modding\ExtractedFiles\12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\Beyond reach"

Define dt.i = ElapsedMilliseconds()
Define.i DirectoryErrorMessage
If Len(RootFolder)
    ;--- Program variables which must be set
    fd\addresse = AllocateMemory(DirectoryOperations::#MemoryBlockSizeStart)    ; allocate memory for Filenames and folder names.
    ; FileDataBlockSizeAdd:
    ; The amount of memory to allocate to the already allocated memory (Optional, Advisable.)
    fd\FileDataBlockSizeAdd = DirectoryOperations::#MemoryBlockSizeAdd
    ; Options
    ; Flags for work operation.
    ; * #FD_RECURSE *
    ; Also take subdirectories
    ; * #FD_FOLDERS *
    ; Only stores foldernames
    ; * #FD_FILES *
    ; Only stores Filenames
    ; * #FD_FULLPATH *
    ; Files/Folders are stored with fullpath. (will not override #FD_Files)
    fd\Options = DirectoryOperations::#FD_RECURSE | DirectoryOperations::#FD_DATECREATED | DirectoryOperations::#FD_FILESIZE
    DirectoryErrorMessage = DirectoryOperations::FileDirectory(RootFolder, "*.xwm", @fd)
    If DirectoryErrorMessage
        MessageRequester("Error.","Something went Shit.. : " + Str(DirectoryErrorMessage))
    Else
        ; ************* Add your own Code here - Below
        MessageRequester("Test!","Files: " + Str(fd\files) + " Folders: " + Str(fd\Folders) + " in " + Str(ElapsedMilliseconds() - dt) + "ms.")
        ;--- local Global Strings variables
        Define fd.DirectoryOperations::DirectoryOperationsAPI
        ; Strings
        Define.s TempName, RootFolder
        ; Integers
        Define.i TempLength

        Define.i x
        If CreateFile(0,"F:\Projects\Modding\ExtractedFiles\Result.txt")
            While fd\Size > x
                TempName = PeekS(fd\addresse + x, -1, #PB_Unicode)
                TempLength = (Len(TempName) + 1) * DirectoryOperations::#Length_Char
                ;WriteStringN(0, "Del " + #DQUOTE$ + TempName + #DQUOTE$, #PB_Ascii)
                WriteStringN(0, TempName, #PB_Ascii)
                x + TempLength
            Wend
            CloseFile(0)
        EndIf
        ; ************* Add your own Code here - Above
    EndIf
    FreeMemory(fd\addresse)
EndIf
GenRabbit
Enthusiast
Enthusiast
Posts: 118
Joined: Wed Dec 31, 2014 5:41 pm

Re: Need for an DirectoryLister?(Mac+Windows) Win Support 25

Post by GenRabbit »

Updated version. Now supports pattern search under windows
Anyone have any idea how to seach that under Mac and Linux?

Code: Select all

DeclareModule DirectoryOperations
    EnableExplicit
    #EXTENDEDFILEDIRECTORY           = 1
    #MODULE_DATEACCESSED             = 0
    #MODULE_DATEMODIFIED             = 0
    #MODULE_FILESIZE                 = 0
    CompilerIf #PB_Compiler_OS = #PB_OS_Windows        
        ; Windows Only                
        #MODULE_DATECREATED              = 1
        #MODULE_ATTRIBUTEHIDDEN          = 0
        #MODULE_ATTRIBUTEARCHIVE         = 0
        #MODULE_ATTRIBUTECOMPRESSED      = 0
        #MODULE_ATTRIBUTENORMAL          = 0
        #MODULE_ATTRIBUTEREADONLY        = 0
        #MODULE_ATTRIBUTESYSTEM          = 0
        #MODULE_ATTRIBUTEENCRYPTED       = 0
    CompilerElse    
        ; Mac & linux Only
        #MODULE_ATTRIBUTELINK            = 0
        #MODULE_ATTRIBUTEREADUSER        = 0
        #MODULE_ATTRIBUTEWRITEUSER       = 0
        #MODULE_ATTRIBUTEEXECUSER        = 0
        #MODULE_ATTRIBUTEREADGROUP       = 0
        #MODULE_ATTRIBUTEWRITEGROUP      = 0
        #MODULE_ATTRIBUTEEXECGROUP       = 0
        #MODULE_ATTRIBUTEREADALL         = 0
        #MODULE_ATTRIBUTEWRITEALL        = 0
        #MODULE_ATTRIBUTEEXECALL         = 0
    CompilerEndIf
    CompilerSelect #PB_Compiler_Processor
        CompilerCase #PB_Processor_x86
            #Length_Integer = 4
        CompilerCase #PB_Processor_x64
            #Length_Integer = 8
    CompilerEndSelect
    
    CompilerSelect #PB_Compiler_OS
        CompilerCase #PB_OS_Windows
            #FolderDelimiter$ = "\"
            #WINDOWS_DIRECTORY   = 16
        CompilerDefault
            #FolderDelimiter$ = "/"
    CompilerEndSelect
    
    CompilerIf #PB_Compiler_Unicode
        #Length_Char = 2
    CompilerElse
        #Length_Char = 1
    CompilerEndIf
    
    ;--- Optional Values for memory allocation
    #MemoryBlockSizeStart = 1024 * 1024 ; Allocated memory 1MB
    #MemoryBlockSizeAdd = 1024 * 1024   ; Allocated memory 1MB
    ;--- Error Flag
    Enumeration ERRMSG_ 10 Step 5
        #ERRMSG_OUT_OF_MEMORY
        #ERRMSG_MEMORY_NOT_ALLOCATED
        #ERRMSG_NO_PATH_SPECIFIED
        #ERRMSG_NO_SUCH_PATH
        #ERRMSG_NO_FILE_OR_FOLDER
    EndEnumeration
    
    ;--- Flags
        EnumerationBinary FD_
            #FD_RECURSE
            #FD_FOLDERS         ; Only Foldername
            #FD_FILES           ; Only Filename
            #FD_FULLPATH        ; Fullpath?
            #FD_FILESIZE        ; Filesize
            CompilerIf #MODULE_DATEMODIFIED
                #FD_DATEMODIFIED
            CompilerEndIf    
            CompilerIf #MODULE_DATEACCESSED
                #FD_DATEACCESSED
            CompilerEndIf    
            CompilerIf #PB_Compiler_OS = #PB_OS_Windows
                ; Window specific flags
                CompilerIf #MODULE_DATECREATED
                    #FD_DATECREATED
                CompilerEndIf    
                
                CompilerIf #MODULE_ATTRIBUTEHIDDEN
                    #FD_FileSystemHidden
                CompilerEndIf    
                CompilerIf #MODULE_ATTRIBUTEARCHIVE
                    #FD_FileSystemArchive
                CompilerEndIf    
                CompilerIf #MODULE_ATTRIBUTECOMPRESSED
                    #FD_FileSystemCompressed
                CompilerEndIf    
                CompilerIf #MODULE_ATTRIBUTEENCRYPTED
                    #FD_FileSystemEncrypted
                CompilerEndIf
                CompilerIf #MODULE_ATTRIBUTENORMAL
                    #FD_FileSystemNormal
                CompilerEndIf    
                CompilerIf #MODULE_ATTRIBUTEREADONLY
                    #FD_FileSystemReadOnly
                CompilerEndIf    
                CompilerIf #MODULE_ATTRIBUTESYSTEM
                    #FD_FileSystemSystem
                CompilerEndIf    
            CompilerElse    
                ; Mac/Linux specific flags
                CompilerIf #MODULE_ATTRIBUTELINK
                    #FD_FileSystemLink
                CompilerEndIf    
                CompilerIf #MODULE_ATTRIBUTEREADUSER
                    #FD_FileSystemReadUser    ; Access flags For the owning user
                CompilerEndIf    
                CompilerIf #MODULE_ATTRIBUTEWRITEUSER
                    #FD_FileSystemWriteUser
                CompilerEndIf    
                CompilerIf #MODULE_ATTRIBUTEEXECUSER
                    #FD_FileSystemExecUser
                CompilerEndIf    
                CompilerIf #MODULE_ATTRIBUTEREADGROUP
                    #FD_FileSystemReadGroup   ; Access flags for the owning user's group
                CompilerEndIf    
                CompilerIf #MODULE_ATTRIBUTEWRITEGROUP
                    #FD_FileSystemWriteGroup
                CompilerEndIf    
                CompilerIf #MODULE_ATTRIBUTEEXECGROUP
                    #FD_FileSystemExecGroup
                CompilerEndIf    
                CompilerIf #MODULE_ATTRIBUTEREADALL
                    #FD_FileSystemReadAll     ; Access flags for all other users
                CompilerEndIf    
                CompilerIf #MODULE_ATTRIBUTEWRITEALL
                    #FD_FileSystemWriteAll
                CompilerEndIf    
                CompilerIf #MODULE_ATTRIBUTEEXECALL
                    #FD_FileSystemExecAll
                CompilerEndIf
            CompilerEndIf
        EndEnumeration
    
        #TIMEFORMAT$ = "%DD-%MM-%YYYY %HH:%II"
        #DATESEPERATOR$ = " "
        #ATTRIBUTESEPERATOR$ = " "
        #FILESIZESEPERATOR$ = " "
    ;--- Macro's begin
        Macro InsertSeperator
            eXtended +
        EndMacro
        Macro Macro_Attributes(FDFLAG, PBFLAG, RESULT1, RESULT2, SEPERATOR)
            If (*fd\Options) & FDFLAG
            CompilerIf #PB_Compiler_OS = #PB_OS_Windows
                If SearchData\dwFileAttributes & PBFLAG  
                    eXtended + RESULT1 + SEPERATOR
                Else
                    eXtended + RESULT2 + SEPERATOR
                EndIf
            CompilerElse
                    If DirectoryEntryAttributes(Exadir) & PBFLAG
                        eXtended + RESULT1 + SEPERATOR
                    Else
                        eXtended + RESULT2 + SEPERATOR
                    EndIf
                EndIf
            CompilerEndIf        
        EndMacro
        
        CompilerIf #MODULE_FILESIZE
            CompilerIf #PB_Compiler_OS = #PB_OS_Windows
                Macro Macro_FileSize
                    If (*fd\Options) & #FD_FILESIZE
                        eXtended + Str((SearchData\nFileSizeHigh * $100000000) + SearchData\nFileSizeLow)
                    EndIf
                EndMacro
                Macro Macro_FileSize_Seperator
                    If (*fd\Options) & #FD_FILESIZE
                        eXtended + Str((SearchData\nFileSizeHigh * $100000000) + SearchData\nFileSizeLow) + #FILESIZESEPERATOR$
                    EndIf
                EndMacro
            CompilerElse
                Macro Macro_FileSize
                    If (*fd\Options) & #FD_FILESIZE
                        eXtended + Str(DirectoryEntrySize(ExaDir))
                    EndIf
                EndMacro
                Macro Macro_FileSize_Seperator
                    If (*fd\Options) & #FD_FILESIZE
                        eXtended + Str(DirectoryEntrySize(ExaDir))+ #FILESIZESEPERATOR$
                    EndIf
                EndMacro
            CompilerEndIf
        CompilerEndIf
    
        CompilerIf #MODULE_DATEMODIFIED
            CompilerIf #PB_Compiler_OS = #PB_OS_Windows
                Macro Macro_DateModified
                    If (*fd\Options) & #FD_DATEMODIFIED
                        FileTime = SearchData\ftLastWriteTime
                        MACRO_DateAndTimeFormat
                        eXtended + FileDate
                   EndIf
                EndMacro        
                Macro Macro_DateModified_Seperator
                    If (*fd\Options) & #FD_DATEMODIFIED
                        FileTime = SearchData\ftLastWriteTime
                        MACRO_DateAndTimeFormat
                        eXtended + FileDate + #DATESEPERATOR$
                   EndIf
                EndMacro        
            CompilerElse
                Macro Macro_DateModified
                    If (*fd\Options) & #FD_DATEMODIFIED
                        eXtended + FormatDate(#TIMEFORMAT$, DirectoryEntryDate(Exadir , #PB_Date_Modified))
                    EndIf
                EndMacro
                Macro Macro_DateModified_Seperator
                    If (*fd\Options) & #FD_DATEMODIFIED
                        eXtended + FormatDate(#TIMEFORMAT$, DirectoryEntryDate(Exadir , #PB_Date_Modified)) + #DATESEPERATOR$
                    EndIf
                EndMacro
            CompilerEndIf        
        CompilerEndIf
    
        CompilerIf #MODULE_DATEACCESSED
            CompilerIf #PB_Compiler_OS = #PB_OS_Windows
                Macro Macro_DateAccessed
                    If (*fd\Options) & #FD_DATEACCESSED
                        FileTime = SearchData\ftLastAccessTime
                        MACRO_DateAndTimeFormat
                        eXtended + FileDate
                    EndIf
                EndMacro
                Macro Macro_DateAccessed_Seperator
                    If (*fd\Options) & #FD_DATEACCESSED
                        FileTime = SearchData\ftLastAccessTime
                        MACRO_DateAndTimeFormat
                        eXtended + FileDate + #DATESEPERATOR$
                    EndIf
                EndMacro                
            CompilerElse
                Macro Macro_DateAccessed
                    If (*fd\Options) & #FD_DATEACCESSED
                        eXtended + FormatDate(#TIMEFORMAT$, DirectoryEntryDate(Exadir , #PB_Date_Accessed))
                    EndIf
                EndMacro
                Macro Macro_DateAccessed_Seperator
                    If (*fd\Options) & #FD_DATEACCESSED
                        eXtended + FormatDate(#TIMEFORMAT$, DirectoryEntryDate(Exadir , #PB_Date_Accessed)) + #DATESEPERATOR$
                    EndIf
                EndMacro
            CompilerEndIf
        CompilerEndIf
        CompilerIf #PB_Compiler_OS = #PB_OS_Windows
            ; Windows Only
            CompilerIf #MODULE_DATECREATED
                Macro Macro_DateCreated
                    If (*fd\Options) & #FD_DATECREATED
                        FileTime = SearchData\ftCreationTime
                        MACRO_DateAndTimeFormat
                        eXtended + FileDate
                    EndIf
                EndMacro
                Macro Macro_DateCreated_Seperator
                    If (*fd\Options) & #FD_DATECREATED
                        FileTime = SearchData\ftCreationTime
                        MACRO_DateAndTimeFormat
                        eXtended + FileDate + #DATESEPERATOR$
                    EndIf
                EndMacro
            CompilerEndIf
    
            CompilerIf #MODULE_ATTRIBUTEHIDDEN
                Macro Macro_Attributehidden
                    Macro_Attributes(#FD_FileSystemHidden, #FILE_ATTRIBUTE_HIDDEN, "[Hidden]", "[]", "")
                EndMacro
                Macro Macro_Attributehidden_Seperator
                    Macro_Attributes(#FD_FileSystemHidden, #FILE_ATTRIBUTE_HIDDEN, "[Hidden]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf
            CompilerIf #MODULE_ATTRIBUTEENCRYPTED
                Macro Macro_AttributeEncrypted
                    Macro_Attributes(#FD_FileSystemEncrypted, #FILE_ATTRIBUTE_ENCRYPTED, "[ENCRYPTED]", "[]", "")
                EndMacro
                Macro Macro_AttributeEncrypted_Seperator
                    Macro_Attributes(#FD_FileSystemEncrypted, #FILE_ATTRIBUTE_ENCRYPTED, "[ENCRYPTED]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf
            
            CompilerIf #MODULE_ATTRIBUTEARCHIVE
                Macro Macro_AttributeArchive
                    Macro_Attributes(#FD_FileSystemHidden, #FILE_ATTRIBUTE_ARCHIVE, "[Archive]", "[]", "")
                EndMacro
                Macro Macro_AttributeArchive_Seperator
                    Macro_Attributes(#FD_FileSystemHidden, #FILE_ATTRIBUTE_ARCHIVE, "[Archive]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf
    
            CompilerIf #MODULE_ATTRIBUTECOMPRESSED
                Macro Macro_AttributeCompressed
                    Macro_Attributes(#FD_FileSystemCompressed, #FILE_ATTRIBUTE_COMPRESSED, "[Compressed]", "[]", "")
                EndMacro
                Macro Macro_AttributeCompressed_Seperator
                    Macro_Attributes(#FD_FileSystemCompressed, #FILE_ATTRIBUTE_COMPRESSED, "[Compressed]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf
    
            CompilerIf #MODULE_ATTRIBUTENORMAL
                Macro Macro_AttributeNormal
                    Macro_Attributes(#FD_FileSystemNormal, #FILE_ATTRIBUTE_NORMAL, "[Normal]", "[]", "")
                EndMacro
                Macro Macro_AttributeNormal_Seperator
                    Macro_Attributes(#FD_FileSystemNormal, #FILE_ATTRIBUTE_NORMAL, "[Normal]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf
    
            CompilerIf #MODULE_ATTRIBUTEREADONLY
                Macro Macro_AttributeReadOnly
                    Macro_Attributes(#FD_FileSystemReadOnly, #FILE_ATTRIBUTE_READONLY, "[Read Only]", "[]", "")
                EndMacro
                Macro Macro_AttributeReadOnly_Seperator
                    Macro_Attributes(#FD_FileSystemReadOnly, #FILE_ATTRIBUTE_READONLY, "[Read Only]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf
    
            CompilerIf #MODULE_ATTRIBUTESYSTEM
                Macro Macro_AttributeSystem
                    Macro_Attributes(#FD_FileSystemSystem, #FILE_ATTRIBUTE_SYSTEM, "[System File]", "[]", "")
                EndMacro
                Macro Macro_AttributeSystem_Seperator
                    Macro_Attributes(#FD_FileSystemSystem, #FILE_ATTRIBUTE_SYSTEM, "[System File]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf
    
        CompilerElse
        ; Mac/Linux Only
            CompilerIf #MODULE_ATTRIBUTELINK
                Macro Macro_AttributeLink
                    Macro_Attributes(#FD_FileSystemLink, #PB_FileSystem_Link, "[Link]", "[]", "")
                EndMacro
                Macro Macro_AttributeLink_Seperator
                    Macro_Attributes(#FD_FileSystemLink, #PB_FileSystem_Link, "[Link]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf
    
            CompilerIf #MODULE_ATTRIBUTEREADUSER
                Macro Macro_AttributeReadUser
                    Macro_Attributes(#FD_FileSystemReadUser, #PB_FileSystem_ReadUser, "[Owning User/Read]", "[]", "")
                EndMacro
                Macro Macro_AttributeReadUser_Seperator
                    Macro_Attributes(#FD_FileSystemReadUser, #PB_FileSystem_ReadUser, "[Owning User/Read]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf
    
            CompilerIf #MODULE_ATTRIBUTEWRITEUSER
                Macro Macro_AttributeWriteUser
                    Macro_Attributes(#FD_FileSystemWriteUser, #PB_FileSystem_WriteUser, "[Owning User/Write]", "[]", "")
                EndMacro
                Macro Macro_AttributeWriteUser_Seperator
                    Macro_Attributes(#FD_FileSystemWriteUser, #PB_FileSystem_WriteUser, "[Owning User/Write]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf
    
            CompilerIf #MODULE_ATTRIBUTEEXECUSER
                Macro Macro_AttributeExecUser
                    Macro_Attributes(#FD_FileSystemExecUser, #PB_FileSystem_ExecUser, "[Owning User/Execute]", "[]", "")
                EndMacro
                Macro Macro_AttributeExecUser_Seperator
                    Macro_Attributes(#FD_FileSystemExecUser, #PB_FileSystem_ExecUser, "[Owning User/Execute]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf
            
            CompilerIf #MODULE_ATTRIBUTEREADGROUP
                Macro Macro_AttributeReadGroup
                    Macro_Attributes(#FD_FileSystemReadGroup, #PB_FileSystem_ReadGroup, "[Owning User Group/Read]", "[]", "")
                EndMacro
                Macro Macro_AttributeReadGroup_Seperator
                    Macro_Attributes(#FD_FileSystemReadGroup, #PB_FileSystem_ReadGroup, "[Owning User Group/Read]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf
    
            CompilerIf #MODULE_ATTRIBUTEWRITEGROUP
                Macro Macro_AttributeWriteGroup
                    Macro_Attributes(#FD_FileSystemWriteGroup, #PB_FileSystem_WriteGroup, "[Owning User Group/Write]", "[]", "")
                EndMacro
                Macro Macro_AttributeWriteGroup_Seperator
                    Macro_Attributes(#FD_FileSystemWriteGroup, #PB_FileSystem_WriteGroup, "[Owning User Group/Write]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf
    
            CompilerIf #MODULE_ATTRIBUTEEXECGROUP
                Macro Macro_AttributeExecGroup
                    Macro_Attributes(#FD_FileSystemExecGroup, #PB_FileSystem_ExecGroup, "[Owning User Group/Exec]", "[]", "")
                EndMacro
                Macro Macro_AttributeExecGroup_Seperator
                    Macro_Attributes(#FD_FileSystemExecGroup, #PB_FileSystem_ExecGroup, "[Owning User Group/Exec]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf
    
            CompilerIf #MODULE_ATTRIBUTEREADALL
                Macro Macro_AttributeReadAll
                    Macro_Attributes(#FD_FileSystemReadAll, #PB_FileSystem_ReadAll, "[All Other Users/Read]", "[]", "")
                EndMacro
                Macro Macro_AttributeReadAll_Seperator
                    Macro_Attributes(#FD_FileSystemReadAll, #PB_FileSystem_ReadAll, "[All Other Users/Read]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf
    
            CompilerIf #MODULE_ATTRIBUTEWRITEALL
                Macro Macro_AttributeWriteAll
                    Macro_Attributes(#FD_FileSystemWriteAll, #PB_FileSystem_WriteAll, "[All Other Users/Write]", "[]", "")
                EndMacro
                Macro Macro_AttributeWriteAll_Seperator
                    Macro_Attributes(#FD_FileSystemWriteAll, #PB_FileSystem_WriteAll, "[All Other Users/Write]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf
    
            CompilerIf #MODULE_ATTRIBUTEEXECALL
                Macro Macro_AttributeExecAll
                    Macro_Attributes(#FD_FileSystemExecAll, #PB_FileSystem_ExecAll, "[All Other Users/Execute]", "[]", "")
                EndMacro
                Macro Macro_AttributeExecAll_Seperator
                    Macro_Attributes(#FD_FileSystemExecAll, #PB_FileSystem_ExecAll, "[All Other Users/Execute]", "[]", #ATTRIBUTESEPERATOR$)
                EndMacro
            CompilerEndIf
        CompilerEndIf
        
        Macro MACRO_DateAndTimeFormat
            FileTimeToLocalFileTime_(@FileTime, @NewFileTime)
            FileTimeToSystemTime_(@NewFileTime,@SYSTEMTIME)
            FileDate = ReplaceString(#TIMEFORMAT$,"%YYYY",Str(SystemTime\wYear), #PB_String_NoCase) ; Year (1601 - 30827)
            FileDate = ReplaceString(FileDate,"%MM",Right("0" + Str(SystemTime\wMonth),2),#PB_String_NoCase) ; Month (1-12)
            FileDate = ReplaceString(FileDate,"%DD",Right("0" + Str(SystemTime\wDay),2),#PB_String_NoCase) ; Day(1-31)
            FileDate = ReplaceString(FileDate,"%HH",Right("0" + Str(SystemTime\wHour),2),#PB_String_NoCase); Hour(0-23)
            FileDate = ReplaceString(FileDate,"%II",Right("0" + Str(SystemTime\wMinute),2),#PB_String_NoCase); Minute(0-59)
            FileDate = ReplaceString(FileDate,"%SS",Right("0" + Str(SystemTime\wSecond),2),#PB_String_NoCase); Minute(0-59)
        EndMacro
        
        Macro Macro_ExtendedDirectory
            ; Macros Begin
            ;macro_FileSize_Seperator
            Macro_DateCreated_Seperator    
            ; Macros End
        EndMacro
        
    ;--- Macro's END
    
    ;--- Structure
    Structure DirectoryOperationsAPI                
        *addresse
        Options.w
        FileDataBlockSizeAdd.i
        Size.i
        Files.i
        Folders.i
        Total.i
    EndStructure
    Declare FileDirectory(RootFolder.s, pattern.s, *fd.DirectoryOperationsAPI)
EndDeclareModule

Module DirectoryOperations
    Global.i FileDataBlockSize
    Procedure.i StoreResult(FilePathOrFilename.s, *Fd.DirectoryOperationsAPI)
        Protected *PathMapNew
        Protected.i LengthToAdd
        Protected.i TempLength = (Len(FilePathOrFilename) + 1) * #Length_Char
        If (*Fd\Size + TempLength) >= FileDataBlockSize
            ; To small block. Time to increase
            If *Fd\FileDataBlockSizeAdd > TempLength
                LengthToAdd = *Fd\FileDataBlockSizeAdd
            Else
                LengthToAdd = TempLength
            EndIf
            
            *PathMapNew = ReAllocateMemory(*Fd\addresse, FileDataBlockSize + LengthToAdd)
            If *PathMapNew
                *Fd\addresse = *PathMapNew
                FileDataBlockSize + LengthToAdd
            Else
                ProcedureReturn #ERRMSG_OUT_OF_MEMORY
            EndIf
        EndIf    
        PokeS(*Fd\addresse + *Fd\Size,FilePathOrFilename)
        *Fd\Total + 1
        *Fd\Size + TempLength
        ProcedureReturn 0
    EndProcedure
    
    Procedure.i RecurseDir(RootFolder.s, PresentRoot.s, Pattern.s, *Fd.DirectoryOperationsAPI)
        Protected.i ExaDir
        Protected.i *PathMapNew
        Protected.s TempName
        Protected.i ForcedQuit
        CompilerIf #EXTENDEDFILEDIRECTORY
            Protected.s eXtended
        CompilerEndIf
        CompilerIf #PB_Compiler_OS = #PB_OS_Windows
            Protected.WIN32_FIND_DATA SearchData
            Protected.SYSTEMTIME SystemTime
            Protected.Filetime FileTime, NewFileTime
            Protected.s FileDate
            Protected.i ErrorValue
            Protected.i PatternSearch
            Protected.i PatternMatch
            If Len(pattern) 
                PatternSearch = #True
            EndIf
            PatternMatch = #True
            ; // ***************************
            ; // Windows
            ; // ***************************
            ExaDir = FindFirstFile_(rootFolder + "*", SearchData)
            If ExaDir
                While FindNextFile_(ExaDir, SearchData)
                    CompilerIf #EXTENDEDFILEDIRECTORY
                        ; Inserts all Attributes/Filehandler macros we have added.
                        Macro_ExtendedDirectory
                    CompilerEndIf
                    TempName = PeekS(@SearchData\cFileName)
                    If SearchData\dwFileAttributes & #WINDOWS_DIRECTORY
                        ;--- Folder
                        ;TempName = PeekS(@SearchData\cFileName)
                        If (TempName <> ".") And (TempName <> "..")
                            *Fd\Folders + 1
                            If (*Fd\Options & #FD_RECURSE)
                                ForcedQuit = RecurseDir(RootFolder + TempName + #FolderDelimiter$, PresentRoot + TempName + #FolderDelimiter$, Pattern, *Fd)
                                If ForcedQuit
                                    Break
                                EndIf
                            EndIf        
                            If PatternSearch
                                If PathMatchSpec_(@Tempname, @pattern)
                                    PatternMatch = #True
                                Else
                                    patternMatch = #False
                                EndIf
                            EndIf
                            If PatternMatch
                                If *Fd\Options & #FD_FOLDERS
                                    ForcedQuit = StoreResult(PresentRoot + TempName + #FolderDelimiter$, *Fd)
                                EndIf
                            EndIf    
                            If ForcedQuit
                                Break
                            EndIf
                        EndIf                 
                    ;--- File
                    Else
                        ;TempName = DirectoryEntryName(ExaDir)
                        *Fd\Files + 1
                        If PatternSearch
                            If PathMatchSpec_(@Tempname, @pattern)
                                PatternMatch = #True
                            Else
                                patternMatch = #False
                            EndIf
                        EndIf
                        If PatternMatch
                            If *Fd\Options & #FD_FILES
                                CompilerIf #EXTENDEDFILEDIRECTORY
                                    ForcedQuit = StoreResult(eXtended + TempName, *Fd)
                                CompilerElse    
                                    ForcedQuit = StoreResult(TempName, *Fd)
                                CompilerEndIf
                            ElseIf Not *Fd\Options & #FD_FOLDERS
                                CompilerIf #EXTENDEDFILEDIRECTORY
                                    ForcedQuit = StoreResult(eXtended + PresentRoot + TempName, *Fd)
                                CompilerElse    
                                    ForcedQuit = StoreResult(PresentRoot + TempName, *Fd)
                                CompilerEndIf
                            EndIf
                        EndIf
                    EndIf
                    If ForcedQuit
                        Break
                    EndIf
                    eXtended = ""
                Wend
                FindClose_(ExaDir)
            Else    
                ProcedureReturn #ERRMSG_NO_SUCH_PATH
            EndIf
            ProcedureReturn ForcedQuit

        CompilerElse
            ; // ***************************
            ; // Mac & Linux
            ; // ***************************
            ExaDir = ExamineDirectory(#PB_Any, RootFolder, Pattern)
            If ExaDir
                While NextDirectoryEntry(ExaDir)
                    CompilerIf #EXTENDEDFILEDIRECTORY
                        ; Inserts all Attributes/Filehandler macros we have added.
                        ExtendedDirectoryMacros
                    CompilerEndIf            
                    Select DirectoryEntryType(ExaDir)
                        ;--- Folder
                        Case #PB_DirectoryEntry_Directory
                            TempName = DirectoryEntryName(ExaDir)
                            If (TempName <> ".") And (TempName <> "..")
                                *Fd\Folders + 1
                                If (*Fd\Options & #FD_RECURSE)
                                    ForcedQuit = RecurseDir(RootFolder + TempName + #FolderDelimiter$, PresentRoot + TempName + #FolderDelimiter$, *Fd)
                                    If ForcedQuit
                                        Break
                                    EndIf
                                EndIf        
                                If *Fd\Options & #FD_FOLDERS
                                    ForcedQuit = StoreResult(PresentRoot + TempName + #FolderDelimiter$, *Fd)
                                EndIf
                                If ForcedQuit
                                    Break
                                EndIf
                            EndIf                 
                        ;--- File
                        Case #PB_DirectoryEntry_File
                            TempName = DirectoryEntryName(ExaDir)
                            *Fd\Files + 1
                            If *Fd\Options & #FD_FILES
                                CompilerIf #EXTENDEDFILEDIRECTORY
                                    ForcedQuit = StoreResult(eXtended + TempName, *Fd)
                                CompilerElse    
                                    ForcedQuit = StoreResult(TempName, *Fd)
                                CompilerEndIf
                            ElseIf Not *Fd\Options & #FD_FOLDERS
                                CompilerIf #EXTENDEDFILEDIRECTORY
                                    ForcedQuit = StoreResult(eXtended + PresentRoot + TempName, *Fd)
                                CompilerElse    
                                    ForcedQuit = StoreResult(PresentRoot + TempName, *Fd)
                                CompilerEndIf
                            EndIf
                    EndSelect
                    If ForcedQuit
                        Break
                    EndIf
                    eXtended = ""
                Wend
                FinishDirectory(ExaDir)
            Else    
                ProcedureReturn #ERRMSG_NO_SUCH_PATH
            EndIf
            ProcedureReturn ForcedQuit
        CompilerEndIf        
    EndProcedure                
    Procedure.i FileDirectory(RootFolder.s, Pattern.s, *fd.DirectoryOperationsAPI)
        ; Initialize values 
        Protected.s subfolder
        Protected.i Result
        Protected *OptimizedBlockSize
        CompilerIf #PB_Compiler_OS = #PB_OS_Windows And #PB_Compiler_Processor = #PB_Processor_x86
            Protected.i Redirection
        CompilerEndIf
        If *fd\addresse
            *fd\Files = 0
            *fd\Folders = 0
            *fd\Size = 0
            *fd\Total = 0
            FileDataBlockSize = MemorySize(*fd\addresse) ; Sets \FileDataBlocksize to the Size of the Allocated buffer.
            If *fd\Options & #FD_FULLPATH
                SubFolder = RootFolder
            EndIf
            If Right(RootFolder,1) <> #FolderDelimiter$
                RootFolder + #FolderDelimiter$
                Result = SetCurrentDirectory_(@RootFolder)
            Else    
                Result = SetCurrentDirectory_(@RootFolder)
            EndIf
            If result
                CompilerIf #PB_Compiler_OS = #PB_OS_Windows And #PB_Compiler_Processor = #PB_Processor_x86
                    Wow64DisableWow64FsRedirection_(@Redirection)
                    Result = RecurseDir(RootFolder, SubFolder ,Pattern, *fd)
                    Wow64RevertWow64FsRedirection_(Redirection)
                CompilerElse
                    Result = RecurseDir(RootFolder, SubFolder ,Pattern, *fd)
                CompilerEndIf
                If Not Result
                    If *fd\Size
                        If FileDataBlockSize > *fd\Size
                            *OptimizedBlockSize = ReAllocateMemory(*Fd\addresse, *fd\Size)
                            If *OptimizedBlockSize
                                *Fd\addresse = *OptimizedBlockSize
                            Else
                                ProcedureReturn #ERRMSG_OUT_OF_MEMORY
                            EndIf
                        EndIf
                    Else
                        ProcedureReturn #ERRMSG_NO_FILE_OR_FOLDER
                    EndIf
                EndIf
            Else
                ProcedureReturn #ERRMSG_NO_SUCH_PATH
            EndIf
        Else
            ProcedureReturn #ERRMSG_MEMORY_NOT_ALLOCATED
        EndIf
    EndProcedure
EndModule
Post Reply