C/C++ User's Journal Synesis Software STLSoft - ... Robust, Lightweight, Cross-platform, Template Software ... ATLSTL - where the Standard Template Library meets the Active Template Library COMSTL - where the Standard Template Library meets the Component Object Model InetSTL - where the Standard Template Library meets the Internet UNIXSTL - Template Software for the UNIX Operating System WinSTL - where the Standard Template Library meets the Win32 API

Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

Test Programs

Introduction

Version 1.4.1 contains nine test programs.

C.c

This program uses the raw recls C API functions, implementing a recursive search for a given pattern, from a given directory

/* 
 * File:        C.c
 *
 * Purpose:     Implementation file for the C project.
 *
 * Created:     15th August 2003
 * Updated:     8th June 2004
 *
 * Status:      Wizard-generated
 *
 * License:     (Licensed under the Synesis Software Open License)
 *
 *              Copyright (C) 1999-2004, Synesis Software Pty Ltd.
 *              All rights reserved.
 *
 *              www:        http://www.synesis.com.au/software
 *
 *              email:      software@synesis.com.au
 *
 *              This source code is placed into the public domain 2003
 *              by Synesis Software Pty Ltd. There are no restrictions
 *              whatsoever to your use of the software. 
 *
 *              This source code is provided by Synesis Software Pty Ltd "as is"
 *              and any warranties, whether expressed or implied, including, but
 *              not limited to, the implied warranties of merchantability and
 *              fitness for a particular purpose are disclaimed. In no event
 *              shall the Synesis Software Pty Ltd be liable for any direct,
 *              indirect, incidental, special, exemplary, or consequential
 *              damages (including, but not limited to, procurement of
 *              substitute goods or services; loss of use, data, or profits; or
 *              business interruption) however caused and on any theory of
 *              liability, whether in contract, strict liability, or tort
 *              (including negligence or otherwise) arising in any way out of
 *              the use of this software, even if advised of the possibility of
 *              such damage. 
 *
 *              Neither the name of Synesis Software Pty Ltd nor the names of
 *              any subdivisions, employees or agents of Synesis Software Pty
 *              Ltd, nor the names of any other contributors to this software
 *              may be used to endorse or promote products derived from this
 *              software without specific prior written permission. 
 *
 */

/* Remove this definition to use platform-specific aspects of the API */
#define RECLS_PURE_API

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <recls.h>
#include <recls_assert.h>

#ifdef RECLS_PLATFORM_IS_UNIX
# include <unistd.h>
#endif /* RECLS_PLATFORM_IS_UNIX */

#ifdef RECLS_COMPILER_IS_BORLAND
# include <malloc.h>
#endif /* RECLS_COMPILER_IS_BORLAND */

#if RECLS_VER < RECLS_VER_1_1_1
# error This file now requires version 1.1.1 or later of the recls C API
#endif /* RECLS_VER < 1.1.1 */

#include <recls_assert.h>

#ifdef _MSC_VER
# include <crtdbg.h>
#endif /* _MSC_VER */

/* 
 * Macros
 */

#ifndef NUM_ELEMENTS
# ifdef __DMC__
# define NUM_ELEMENTS(x)        (sizeof(x) / sizeof((x)[0]))
# else /* ? compiler */
# define NUM_ELEMENTS(x)        (sizeof(x) / sizeof(0[(x)]))
# endif /* compiler */
#endif /* !NUM_ELEMENTS */

/* 
 * Constants and definitions
 */

static size_t path_max(void)
{
#if defined(WIN32)
        return 1 + _MAX_PATH;
#elif defined(PATH_MAX)
        return 1 + PATH_MAX;
#else /* ? PATH_MAX */
        return 1 + 1 + pathconf("/", _PC_PATH_MAX);
#endif /* PATH_MAX */
}

#ifdef _MSC_VER
# define alloca _alloca
#endif /* _MSC_VER */

#define alloca_path()   ((recls_char_t*)alloca(path_max()))

/* 
 * Forward declarations
 */

static void usage(int bExit, char const *reason);
int processDirectory(char const *rootDir, char const *pattern, long flags, int bSuccinct);

/* 
 * Main
 */

int main(int argc, char *argv[])
{
#if defined(_MSC_VER) && \
    defined(_DEBUG)
    _CrtMemState    memState;
#endif /* _MSC_VER && _MSC_VER */
    int             iRet            =   0;
    int             i;
    int             totalFound      =   0;
    int             bAllHardDrives  =   0;
    char const      *host               =   NULL;
    char const      *username       =   NULL;
    char const      *password       =   NULL;
    char const      *pattern        =   NULL;
    char const      *rootDir        =   NULL;
    recls_uint32_t  flags           =   RECLS_F_RECURSIVE;
    int             bSuccinct       =   0;

    for(i = 1; i < argc; ++i)
    {
        const char  *arg    =   argv[i];

        if(arg[0] == '-')
        {
            if(arg[1] == '-')
            {
                /* -- arguments */
            }
            else
            {
                /* - arguments */
                switch(arg[1])
                {
                    case    '?':
                        usage(1, NULL);
                        break;
                    case    'R':    /* Do not recurse */
                        flags &= ~(RECLS_F_RECURSIVE);
                        break;
                    case    'p':    /* Show directory parts */
                        flags |= RECLS_F_DIRECTORY_PARTS;
                        break;
                    case    'f':    /* Find files */
                        flags |= RECLS_F_FILES;
                        break;
                    case    'd':    /* Find directories */
                        flags |= RECLS_F_DIRECTORIES;
                        break;
                    case    'h':    /* Searches from hard drives */
                        bAllHardDrives = 1;
                        break;
                    case    's':    /* Show only the full path; WHEREIS functionality */
                        bSuccinct = 1;
                        break;
                    case    'H':    /* FTP host */
                        host = arg + 2;
                        break;
                    case    'U':    /* FTP username */
                        username = arg + 2;
                        break;
                    case    'P':    /* FTP password */
                        password = arg + 2;
                        break;
                    default:
                        usage(1, "Invalid argument(s) specified");
                        break;
                }
            }
        }
        else
        {
            /* other arguments */
            if(NULL == pattern)
            {
                pattern = arg;
            }
            else if(NULL == rootDir)
            {
                rootDir = arg;
            }
            else
            {
                usage(1, "Invalid argument(s) specified");
            }
        }
    }

        if( NULL != password &&
                (       NULL == host ||
                        NULL == username))
        {
                usage(1, "Must specify host and username if specifying password");
        }

        if( NULL != username &&
                NULL == host)
        {
                usage(1, "Must specify host if specifying username");
        }

        if( NULL != host &&
                bAllHardDrives)
        {
                usage(1, "-h flag meaningless to FTP searches");
        }

    if( NULL != host &&
                NULL == rootDir)
    {
                usage(1, "Must specify a root directory for FTP searches");
    }

#if defined(_MSC_VER) && \
    defined(_DEBUG)
    _CrtMemCheckpoint(&memState);
#endif /* _MSC_VER && _MSC_VER */

    /* Search for files if neither files or directories specified/
     *
     * Even though this is not necessary, because the recls API provides the
     * same interpretation, it's best to be explicit.
     */
    if(0 == (flags & (RECLS_F_FILES | RECLS_F_DIRECTORIES)))
    {
        flags |= RECLS_F_FILES;
    }

    if(NULL == pattern)
    {
        pattern = Recls_GetWildcardsAll();
    }

    if(NULL == rootDir)
    {
        rootDir = ".";
    }

        /* Check the size of rootDir */
#ifdef x_DEBUG
        {
                recls_bool_t            bEmpty  =       Recls_IsDirectoryEmpty(rootDir);

                recls_filesize_t        size    =       Recls_CalcDirectorySize(rootDir);

                ((void)bEmpty);
                ((void)size);
        }
#endif /* _DEBUG */

    /* Initiate the search. */
    if(bAllHardDrives)
    {
        recls_root_t    roots[26];
        size_t          cRoots  =   Recls_GetRoots(roots, NUM_ELEMENTS(roots));
        size_t          i;

        for(i = 0; i < cRoots; ++i)
        {
            totalFound += processDirectory(roots[i].name, pattern, flags, bSuccinct);
        }
    }
    else
    {
        totalFound = processDirectory(rootDir, pattern, flags, bSuccinct);
    }

    fprintf(stdout, "Total found: %d\n", totalFound);

#if defined(_MSC_VER) && \
    defined(_DEBUG)
    _CrtMemDumpAllObjectsSince(&memState);
#endif /* _MSC_VER && _MSC_VER */

    return iRet;
}

/* 
 * Function implementations
 */

void usage(int bExit, char const *reason)
{
    fprintf(stderr, "recls C Test Program\n\n");

        if(NULL != reason)
        {
                fprintf(stderr, "  Error: %s\n\n", reason);
        }

    fprintf(stderr, "Usage: C++ [-d] [-f] [-h] [-p] [-R] [-s] [-H<host>] [-U<username>] [-P<password>] [<pattern>] [<root-dir>]\n");
    fprintf(stderr, "\t-R               -   does not recurse; recursive search is the default\n");
    fprintf(stderr, "\t-p               -   evaluate and display directory parts\n");
    fprintf(stderr, "\t-d               -   search for directories\n");
    fprintf(stderr, "\t-f               -   search for files (this is the default, if -d is not specified)\n");
    fprintf(stderr, "\t-h               -   searches from hard drive roots. (Ignore <root-dir>.)\n");
    fprintf(stderr, "\t-s               -   succinct; shows only the path\n");
        fprintf(stderr, "\t-H<host>         -   performs an FTP search on the given host\n");
        fprintf(stderr, "\t-U<username>     -   username to use to log on to <host>\n");
        fprintf(stderr, "\t-P<password>     -   password to use to log on to <host>\n");
    fprintf(stderr, "\t<pattern>        -   search pattern, e.g. \"*.cpp\" (default is to search for all files)\n");
    fprintf(stderr, "\t<root-dir>       -   root directory of search; default is current working directory\n");

    if(bExit)
    {
        exit(EXIT_FAILURE);
    }
}

int processDirectory(char const *rootDir, char const *pattern, long flags, int bSuccinct)
{
    hrecls_t    hSrch;
    recls_rc_t  rc          =   Recls_Search(rootDir, pattern, flags, &hSrch);
    int         totalFound  =   0;

    if(RECLS_FAILED(rc))
    {
        recls_char_t    err[100];

        Recls_GetErrorString(rc, err, 100);

        fprintf(stderr, "Failed to start search, with pattern \"%s\"; recls error: %s\n", pattern, err);
    }
    else
    {
        /* Iterate through the items, until done */
        recls_info_t    info;

        rc = Recls_GetDetails(hSrch, &info);

        for(; RECLS_SUCCEEDED(rc); rc = Recls_GetNextDetails(hSrch, &info))
        {
            int             i;
            int             off;
            int             extLen;
            int             cDirParts;
            recls_char_t    *path               =       alloca_path();
#ifdef RECLS_PLATFORM_API_WIN32
            recls_char_t    *drive;
#endif /* RECLS_PLATFORM_API_WIN32 */
            recls_char_t    *dir                =       alloca_path();
            recls_char_t    *dirPath    =       alloca_path();
            recls_char_t    *file               =       alloca_path();
            recls_char_t    *fileName   =       alloca_path();
            recls_char_t    *fileExt    =       alloca_path();

            recls_char_t    *pathCheck  =       alloca_path();
            recls_char_t    *dirCheck   =       alloca_path();
            recls_char_t    *fileCheck  =       alloca_path();

            ++totalFound;

            pathCheck[0] = '\0';
            dirCheck[0] = '\0';
            fileCheck[0] = '\0';

#ifdef x_DEBUG
            {
                recls_uint32_t  cBlocks;
                Recls_OutstandingDetails(hSrch, &cBlocks);
                printf("\n%d outstanding blocks\n", cBlocks);
            }
#endif /* _DEBUG */

            Recls_GetPathProperty(info, path, path_max());
            printf("  %s\n", path);
            if(!bSuccinct)
            {
                Recls_GetDirectoryPathProperty(info, dirPath, path_max());
                printf("  %s\n", dirPath);
#ifdef RECLS_PLATFORM_API_WIN32
                Recls_GetDriveProperty(info, &drive);
                if(isupper(path[0]))
                {
                    drive = (recls_char_t)toupper(drive);
                }
                else
                {
                    drive = (recls_char_t)tolower(drive);
                }
                printf("  %c\n", drive);
                sprintf(pathCheck, "%c:", drive);
                off = 2;
#elif defined(RECLS_PLATFORM_IS_WIN32)
                off = 2;
#else /* platform */
                off = 0;
#endif /* RECLS_PLATFORM_API_WIN32 */
                Recls_GetDirectoryProperty(info, dir, path_max());
                printf("  %*s\n", off + strlen(dir), dir);

                if((flags & RECLS_F_DIRECTORY_PARTS) == RECLS_F_DIRECTORY_PARTS)
                {
                    for(i = 0, cDirParts = Recls_GetDirectoryPartProperty(info, -1, NULL, 0); i < cDirParts; ++i)
                    {
                        recls_char_t    *dirPart        =       alloca_path();

                        off += Recls_GetDirectoryPartProperty(info, i, dirPart, path_max());
                        printf("  %*s\n", off, dirPart);

                        strcat(pathCheck, dirPart);
                        strcat(dirCheck, dirPart);
                    }
                }
                else
                {
                    off += strlen(dir);
                    strcat(pathCheck, dir);
                }

                off +=   Recls_GetFileProperty(info, file, path_max());
                         Recls_GetFileNameProperty(info, fileName, path_max());
                extLen = Recls_GetFileExtProperty(info, fileExt, path_max());
                printf("  %*s\n", off, file);
                printf("  %*s\n", off - (0 != extLen ? 1 + extLen : 0), fileName);
                printf("  %*s\n", off, fileExt);
                strcpy(fileCheck, fileName);
                if(0 < extLen)
                {
                    strcat(fileCheck, ".");
                    strcat(fileCheck, fileExt);
                }

                strcat(pathCheck, file);

                /* Now validate the components */
#if defined(RECLS_PLATFORM_IS_WIN32) && \
    !defined(RECLS_PLATFORM_API_WIN32)
                recls_assert(0 == strcmp(path + 2, pathCheck));
                if(0 != strcmp(path + 2, pathCheck))
#else /* ? RECLS_PLATFORM_API_WIN32 */
                recls_assert(0 == strcmp(path, pathCheck));
                if(0 != strcmp(path, pathCheck))
#endif /* RECLS_PLATFORM_API_WIN32 || !RECLS_PLATFORM_IS_WIN32 */
                {
                    fprintf(stderr, "Path is different from path components\n\tpath:  %s\n\tparts: %s\n\n", path, pathCheck);

                    abort();
                }
#if defined(RECLS_PLATFORM_API_WIN32)
                recls_assert(dirPath[0] == drive && 0 == strcmp(dir, dirPath + 2));
                if( dirPath[0] != drive ||
                    0 != strcmp(dir, dirPath + 2))
#elif defined(RECLS_PLATFORM_IS_WIN32)
                recls_assert(0 == strcmp(dir, dirPath + 2));
                if(0 != strcmp(dir, dirPath + 2))
#else
                recls_assert(0 == strcmp(dir, dirPath));
                if(0 != strcmp(dir, dirPath))
#endif /* RECLS_PLATFORM_API_WIN32 || !RECLS_PLATFORM_IS_WIN32 */
                {
                    fprintf(stderr, "DirectoryPath is different from Directory\n\tdirPath:  %s\n\tdir: %s\n\n", dirPath, dir);

                    abort();
                }
                if((flags & RECLS_F_DIRECTORY_PARTS) == RECLS_F_DIRECTORY_PARTS)
                {
                    recls_assert(0 == strcmp(dir, dirCheck));
                    if(0 != strcmp(dir, dirCheck))
                    {
                        fprintf(stderr, "Directory is different from directory components\n\tpath:  %s\n\tparts: %s\n\n", dir, dirCheck);

                        abort();
                    }
                }
                recls_assert(0 == strcmp(file, fileCheck));
                if(0 != strcmp(file, fileCheck))
                {
                    fprintf(stderr, "File is different from file components\n\tpath:  %s\n\tparts: %s\n\n", file, fileCheck);

                    abort();
                }

                if(Recls_IsFileReadOnly(info))
                {
                    printf("    - Read-only\n");
                }
                if(Recls_IsFileDirectory(info))
                {
                    printf("    - Directory\n");
                }
                else
                {
                    printf("    - File\n");
                }
                if(Recls_IsFileLink(info))
                {
                    printf("    - Link\n");
                }
            }

            Recls_CloseDetails(info);
        }

        if(rc != RECLS_RC_NO_MORE_DATA)
        {
            recls_char_t    err[100];

            Recls_GetErrorString(rc, err, 100);

            fprintf(stderr, "Search terminated prematurely; recls error: %s\n", err);
        }

        Recls_SearchClose(hSrch);
    }

    return totalFound;
}

/* 
 * End of file
 */

Cpp.cpp

This program uses the recls C++ mapping classes, implementing a recursive search for a given pattern, from a given directory (Win32 platform)

/* 
 * File:        Cpp.cpp
 *
 * Purpose:     Implementation file for the Cpp project.
 *
 * Created:     16th August 2003
 * Updated:     8th June 2004
 *
 * Status:      Wizard-generated
 *
 * License:     (Licensed under the Synesis Software Open License)
 *
 *              Copyright (C) 1999-2004, Synesis Software Pty Ltd.
 *              All rights reserved.
 *
 *              www:        http://www.synesis.com.au/software
 *
 *              email:      software@synesis.com.au
 *
 *              This source code is placed into the public domain 2003
 *              by Synesis Software Pty Ltd. There are no restrictions
 *              whatsoever to your use of the software. 
 *
 *              This source code is provided by Synesis Software Pty Ltd "as is"
 *              and any warranties, whether expressed or implied, including, but
 *              not limited to, the implied warranties of merchantability and
 *              fitness for a particular purpose are disclaimed. In no event
 *              shall the Synesis Software Pty Ltd be liable for any direct,
 *              indirect, incidental, special, exemplary, or consequential
 *              damages (including, but not limited to, procurement of
 *              substitute goods or services; loss of use, data, or profits; or
 *              business interruption) however caused and on any theory of
 *              liability, whether in contract, strict liability, or tort
 *              (including negligence or otherwise) arising in any way out of
 *              the use of this software, even if advised of the possibility of
 *              such damage. 
 *
 *              Neither the name of Synesis Software Pty Ltd nor the names of
 *              any subdivisions, employees or agents of Synesis Software Pty
 *              Ltd, nor the names of any other contributors to this software
 *              may be used to endorse or promote products derived from this
 *              software without specific prior written permission. 
 *
 */

/* Define this definition to retrict use to platform-independent aspects of the API */
//#define RECLS_PURE_API

#include <stdio.h>

#include <recls.h>

#if RECLS_VER < RECLS_VER_1_1_1
# error This file now requires version 1.1.1 or later of the recls C API
#endif /* RECLS_VER < 1.1.1 */

#if defined(RECLS_STRICT) && \
    !defined(RECLS_COMPILER_IS_DMC)
# include <stlsoft_nulldef.h>
#endif /* RECLS_STRICT && !RECLS_COMPILER_IS_DMC */

#ifdef _MSC_VER
# include <crtdbg.h>
# pragma warning(disable : 4530)
#endif /* _MSC_VER */

#if RECLS_VER >= RECLS_VER_1_5_1 && \
    defined(RECLS_PLATFORM_IS_WIN32)
# define RECLS_TEST_CPP_USING_FTP
#endif /* RECLS_VER >= RECLS_VER_1_5_1 && RECLS_PLATFORM_IS_WIN32 */

#include <recls_assert.h>
#include <reclspp.h>
#include <reclspp_filesearch.h>
#if defined(RECLS_TEST_CPP_USING_FTP)
# include <reclspp_ftpsearch.h>
#endif /* RECLS_TEST_CPP_USING_FTP */

/* 
 * Namespace
 */

using recls::recls_uint32_t;
using recls::recls_char_t;
using recls::RECLS_F_FILES;
using recls::RECLS_F_DIRECTORIES;
using recls::RECLS_F_RECURSIVE;
using recls::RECLS_F_DIRECTORY_PARTS;

/* 
 * Forward declarations
 */

static void usage(int bExit, char const *reason);
static int processSearch(reclspp::Search &search, int bSuccinct, recls_uint32_t flags);

/* 
 * Main
 */

int main(int argc, char *argv[])
{
#if defined(_MSC_VER) && \
    defined(_DEBUG)
    _CrtMemState        memState;
#endif /* _MSC_VER && _MSC_VER */
    int             iRet                        =   0;
    int             i;
    int             totalFound;
    int             bAllHardDrives  =   0;
    char const      *host               =   NULL;
    char const      *username       =   NULL;
    char const      *password       =   NULL;
    char const      *pattern            =   NULL;
    char const      *rootDir            =   NULL;
    recls_uint32_t  flags                       =   RECLS_F_RECURSIVE;
    int             bSuccinct           =   false;

    for(i = 1; i < argc; ++i)
    {
        const char  *arg    =   argv[i];

        if(arg[0] == '-')
        {
            if(arg[1] == '-')
            {
                /* -- arguments */
            }
            else
            {
                /* - arguments */
                switch(arg[1])
                {
                    case    '?':
                        usage(1, NULL);
                        break;
                    case    'R':    /* Do not recurse */
                        flags &= ~(RECLS_F_RECURSIVE);
                        break;
                    case    'p':    /* Show directory parts */
                        flags |= RECLS_F_DIRECTORY_PARTS;
                        break;
                    case    'f':    /* Find files */
                        flags |= RECLS_F_FILES;
                        break;
                    case    'd':    /* Find directories */
                        flags |= RECLS_F_DIRECTORIES;
                        break;
                    case    'h':    /* Searches from hard drives */
                        bAllHardDrives = true;
                        break;
                    case    's':    /* Show only the full path; WHEREIS functionality */
                        bSuccinct = true;
                        break;
                    case    'H':    /* FTP host */
                        host = arg + 2;
                        break;
                    case    'U':    /* FTP username */
                        username = arg + 2;
                        break;
                    case    'P':    /* FTP password */
                        password = arg + 2;
                        break;
                    default:
                        usage(1, "Invalid argument(s) specified");
                        break;
                }
            }
        }
        else
        {
            /* other arguments */
            if(NULL == pattern)
            {
                pattern = arg;
            }
            else if(NULL == rootDir)
            {
                rootDir = arg;
            }
            else
            {
                usage(1, "Invalid argument(s) specified");
            }
        }
    }

        if( NULL != password &&
                (       NULL == host ||
                        NULL == username))
        {
                usage(1, "Must specify host and username if specifying password");
        }

        if( NULL != username &&
                NULL == host)
        {
                usage(1, "Must specify host if specifying username");
        }

        if( NULL != host &&
                bAllHardDrives)
        {
                usage(1, "-h flag meaningless to FTP searches");
        }

    if( NULL != host &&
                NULL == rootDir)
    {
                usage(1, "Must specify a root directory for FTP searches");
    }

#if defined(_MSC_VER) && \
    defined(_DEBUG)
    _CrtMemCheckpoint(&memState);
#endif /* _MSC_VER && _MSC_VER */

    // Search for files if neither files or directories specified
    //
    // Even though this is not necessary, because the recls API provides the
    // same interpretation, it's best to be explicit.
    if(0 == (flags & (RECLS_F_FILES | RECLS_F_DIRECTORIES)))
    {
        flags |= RECLS_F_FILES;
    }

        /* Now conduct the search */
#if defined(RECLS_TEST_CPP_USING_FTP)
        if(NULL != host)
    {
                if(NULL == pattern)
                {
                        pattern = recls::Recls_GetWildcardsAll();
                }

                if(NULL == rootDir)
                {
                        rootDir = "/";
                }

                reclspp::FtpSearch      search(host, username, password, rootDir, pattern, flags);

                totalFound = processSearch(search, bSuccinct, flags);
        }
        else
#endif /* RECLS_TEST_CPP_USING_FTP */
        {
                if(NULL == pattern)
                {
                        pattern = recls::Recls_GetWildcardsAll();
                }

                if(NULL == rootDir)
                {
                        rootDir = ".";
                }

                reclspp::FileSearch     search(rootDir, pattern, flags);

                totalFound = processSearch(search, bSuccinct, flags);
        }

    fprintf(stdout, "Total found: %d\n", totalFound);

#if defined(_MSC_VER) && \
    defined(_DEBUG)
    _CrtMemDumpAllObjectsSince(&memState);
#endif /* _MSC_VER && _MSC_VER */

    return iRet;
}

/* 
 * Function implementations
 */

static void usage(int bExit, char const *reason)
{
    fprintf(stderr, "recls C++ Test Program\n\n");

        if(NULL != reason)
        {
                fprintf(stderr, "  Error: %s\n\n", reason);
        }

    fprintf(stderr, "Usage: Cpp [-d] [-f] [-h] [-p] [-R] [-s] [-H<host>] [-U<username>] [-P<password>] [<pattern>] [<root-dir>]\n");
    fprintf(stderr, "\t-R               -   does not recurse; recursive search is the default\n");
    fprintf(stderr, "\t-p               -   evaluate and display directory parts\n");
    fprintf(stderr, "\t-d               -   search for directories\n");
    fprintf(stderr, "\t-f               -   search for files (this is the default, if -d is not specified)\n");
    fprintf(stderr, "\t-h               -   searches from hard drive roots. (Ignore <root-dir>.)\n");
    fprintf(stderr, "\t-s               -   succinct; shows only the path\n");
        fprintf(stderr, "\t-H<host>         -   performs an FTP search on the given host\n");
        fprintf(stderr, "\t-U<username>     -   username to use to log on to <host>\n");
        fprintf(stderr, "\t-P<password>     -   password to use to log on to <host>\n");
    fprintf(stderr, "\t<pattern>        -   search pattern, e.g. \"*.cpp\"; default is to search for all files\n");
    fprintf(stderr, "\t<root-dir>       -   root directory of search; default is current working directory\n");

    if(bExit)
    {
        exit(EXIT_FAILURE);
    }
}

/* 
 * Function implementations
 */

static int processSearch(reclspp::Search &search, int bSuccinct, recls_uint32_t flags)
{
        int     totalFound      =       0;

    for(; search.HasMoreElements(); search.GetNext())
    {
        using reclspp::string_t;

        ++totalFound;

        reclspp::FileEntry      fileEntry   =   search.GetCurrentEntry();
#ifdef RECLS_PLATFORM_API_WIN32
        recls_char_t            drive       =   fileEntry.GetDrive();
#endif /* RECLS_PLATFORM_API_WIN32 */
        string_t                path        =   fileEntry.GetPath();
        string_t                dir         =   fileEntry.GetDirectory();
        string_t                dirPath     =   fileEntry.GetDirectoryPath();
        reclspp::DirectoryParts dirParts    =   fileEntry.GetDirectoryParts();
        string_t                file        =   fileEntry.GetFile();
        string_t                fileName    =   fileEntry.GetFileName();
        string_t                fileExt     =   fileEntry.GetFileExt();

        string_t                pathCheck;
        string_t                dirPartsCheck;
        string_t                fileCheck;

#ifdef x_DEBUG
        reclspp::FileEntry  entry2;

        if( fileEntry
            && !entry2)
        {
            fprintf(stderr, "Good entry\n");
        }
        if(!fileEntry)
        {
            fprintf(stderr, "Bad entry\n");
        }
#endif /* _DEBUG */

#ifdef _DEBUG
        {
            recls_uint32_t  cBlocks = search.GetNumOutstandingDetails();

            printf("\n%d outstanding block(s)\n", cBlocks);
        }
#endif /* _DEBUG */

        printf("  %s\n", path.c_str());
        if(!bSuccinct)
        {
            int     off =   0;

            printf("  %s\n", dirPath.c_str());
#ifdef RECLS_PLATFORM_API_WIN32
                        if(0 != drive)
                        {
                                if(isupper(path[0]))
                                {
                                        drive = (recls_char_t)toupper(drive);
                                }
                                else
                                {
                                        drive = (recls_char_t)tolower(drive);
                                }
                                printf("  %c\n", drive);
                                pathCheck += drive;
                                pathCheck += ':';

                                off += 2;
                        }
#endif /* RECLS_PLATFORM_API_WIN32 */
            printf("    %s\n", dir.c_str());

            if((flags & RECLS_F_DIRECTORY_PARTS) == RECLS_F_DIRECTORY_PARTS)
            {
                int     i;
                int     cDirParts;

                for(i = 0, cDirParts = dirParts.size(); i < cDirParts; ++i)
                {
                    string_t    dirPart =   dirParts[i];

                    off += dirPart.length();
                    printf("    %*s\n", off, dirPart.c_str());

                    pathCheck += dirPart;
                    dirPartsCheck += dirPart;
                }
            }
            else
            {
                off += dir.length();
                pathCheck += dir;
            }

            off += file.length();
            printf("    %*s\n", off, file.c_str());
            if(fileExt.length() > 0)
            {
                printf("    %*s\n", off - (1 + fileExt.length()), fileName.c_str());
                printf("    %*s\n", off, fileExt.c_str());
            }
            else
            {
                printf("    %*s\n", off, fileName.c_str());
            }

            fileCheck = fileName;
            if(0 < fileExt.length())
            {
                fileCheck += '.';
                fileCheck += fileExt;
            }

            pathCheck += file;

            // Now validate the components
            recls_assert(path == pathCheck);
            if(path != pathCheck)
            {
                fprintf(stderr, "Path is different from path components\n\tpath:  %s\n\tparts: %s\n\n", path.c_str(), pathCheck.c_str());

                abort();
            }
#ifdef RECLS_PLATFORM_API_WIN32
            recls_assert(0 == drive || (dirPath[0] == drive && dir == dirPath.c_str() + 2));
            recls_assert(0 != drive || dir == dirPath);
            if( (       0 != drive &&
                                        (       dirPath[0] != drive ||
                                                dir != dirPath.c_str() + 2)) ||
                                (       0 == drive &&
                                        dir != dirPath))
#else
            recls_assert(dirPath == dir);
            if(dirPath != dir)
#endif /* RECLS_PLATFORM_API_WIN32 */
            {
                fprintf(stderr, "DirectoryPath is different from Directory\n\tdirPath:  %s\n\tdir: %s\n\n", dirPath.c_str(), dir.c_str());

                abort();
            }
            if((flags & RECLS_F_DIRECTORY_PARTS) == RECLS_F_DIRECTORY_PARTS)
            {
                recls_assert(dir == dirPartsCheck);
                if(dir != dirPartsCheck)
                {
                    fprintf(stderr, "Directory is different from directory components\n\tpath:  %s\n\tparts: %s\n\n", dir.c_str(), dirPartsCheck.c_str());

                    abort();
                }
            }
            recls_assert(file == fileCheck);
            if(file != fileCheck)
            {
                fprintf(stderr, "File is different from file components\n\tpath:  %s\n\tparts: %s\n\n", file.c_str(), fileCheck.c_str());

                abort();
            }

            if(fileEntry.IsReadOnly())
            {
                printf("    - Read-only\n");
            }
            if(fileEntry.IsDirectory())
            {
                printf("    - Directory\n");
            }
            else
            {
                printf("    - File\n");
            }
            if(fileEntry.IsLink())
            {
                printf("    - Link\n");
            }
        }
        }

        return totalFound;
}

/* 
 * End of file
 */

STL.cpp

This program uses the recls STL mapping classes, implementing a recursive search for a given pattern, from a given directory

/* 
 * File:        STL.cpp
 *
 * Purpose:     Implementation file for the STL project.
 *
 * Created:     16th August 2003
 * Updated:     8th June 2004
 *
 * Status:      Wizard-generated
 *
 * License:     (Licensed under the Synesis Software Open License)
 *
 *              Copyright (C) 1999-2004, Synesis Software Pty Ltd.
 *              All rights reserved.
 *
 *              www:        http://www.synesis.com.au/software
 *
 *              email:      software@synesis.com.au
 *
 *              This source code is placed into the public domain 2003
 *              by Synesis Software Pty Ltd. There are no restrictions
 *              whatsoever to your use of the software. 
 *
 *              This source code is provided by Synesis Software Pty Ltd "as is"
 *              and any warranties, whether expressed or implied, including, but
 *              not limited to, the implied warranties of merchantability and
 *              fitness for a particular purpose are disclaimed. In no event
 *              shall the Synesis Software Pty Ltd be liable for any direct,
 *              indirect, incidental, special, exemplary, or consequential
 *              damages (including, but not limited to, procurement of
 *              substitute goods or services; loss of use, data, or profits; or
 *              business interruption) however caused and on any theory of
 *              liability, whether in contract, strict liability, or tort
 *              (including negligence or otherwise) arising in any way out of
 *              the use of this software, even if advised of the possibility of
 *              such damage. 
 *
 *              Neither the name of Synesis Software Pty Ltd nor the names of
 *              any subdivisions, employees or agents of Synesis Software Pty
 *              Ltd, nor the names of any other contributors to this software
 *              may be used to endorse or promote products derived from this
 *              software without specific prior written permission. 
 *
 * 

// Define this definition to retrict use to platform-independent aspects of the API
//#define RECLS_PURE_API

// Define this to copy file entries into a vector, to exercise the copy semantics
//#define TAKE_COPIES_IN_VECTOR

#include <recls.h>
#ifdef RECLS_PLATFORM_IS_WIN32
# include <recls_ftp.h>
#endif /* RECLS_PLATFORM_IS_WIN32 */


#if RECLS_VER < RECLS_VER_1_1_1
# error This file now requires version 1.1.1 or later of the recls C API
#endif /* RECLS_VER < 1.1.1 */

#ifdef RECLS_STRICT
# include <stlsoft_nulldef.h>
#endif // RECLS_STRICT

#ifdef _MSC_VER
# include <crtdbg.h>
# pragma warning(disable : 4530)
#endif /* _MSC_VER */

#include <reclstl.h>
#include <reclstl_root_sequence.h>
#include <reclstl_search_sequence.h>

#if !defined(RECLS_COMPILER_IS_DMC)
# include <iostream>
# include <iomanip>
#else /* ? compiler */
# include <iostream.h>
# include <iomanip.h>
#endif /* compiler */

#include <stdio.h>

/* 
 * Namespace
 */

#if !defined(RECLS_COMPILER_IS_DMC)
using std::cout;
using std::cerr;
using std::endl;
using std::setw;
#endif /* compiler */
using recls::recls_info_t;
using recls::recls_char_t;
using recls::RECLS_F_FILES;
using recls::RECLS_F_DIRECTORIES;
using recls::RECLS_F_RECURSIVE;
using recls::RECLS_F_DIRECTORY_PARTS;

/* 
 * Forward declarations
 */

static void usage(int bExit, char const *reason);
int processDirectory(char const *host, char const *username, char const *password, char const *rootDir, char const *pattern, long flags, int bSuccinct);

/* 
 * Main
 */

int main(int argc, char *argv[])
{
#if defined(_MSC_VER) && \
    defined(_DEBUG)
    _CrtMemState    memState;
#endif /* _MSC_VER && _MSC_VER */
    int             iRet            =   0;
    int             i;
    int             totalFound      =   0;
    char const      *host               =   NULL;
    char const      *username       =   NULL;
    char const      *password       =   NULL;
    char const      *pattern        =   NULL;
    char const      *rootDir        =   NULL;
    unsigned        flags           =   RECLS_F_RECURSIVE;
    int             bSuccinct       =   false;
    int             bAllHardDrives  =   false;

    for(i = 1; i < argc; ++i)
    {
        const char  *arg    =   argv[i];

        if(arg[0] == '-')
        {
            if(arg[1] == '-')
            {
                /* -- arguments */
            }
            else
            {
                /* - arguments */
                switch(arg[1])
                {
                    case    '?':
                        usage(1, NULL);
                        break;
                    case    'R':    /* Do not recurse */
                        flags &= ~(RECLS_F_RECURSIVE);
                        break;
                    case    'p':    /* Show directory parts */
                        flags |= RECLS_F_DIRECTORY_PARTS;
                        break;
                    case    'f':    /* Find files */
                        flags |= RECLS_F_FILES;
                        break;
                    case    'd':    /* Find directories */
                        flags |= RECLS_F_DIRECTORIES;
                        break;
                    case    'h':    /* Searches from hard drives */
                        bAllHardDrives = 1;
                        break;
                    case    's':    /* Show only the full path; WHEREIS functionality */
                        bSuccinct = true;
                        break;
                    case    'H':    /* FTP host */
                        host = arg + 2;
                        break;
                    case    'U':    /* FTP username */
                        username = arg + 2;
                        break;
                    case    'P':    /* FTP password */
                        password = arg + 2;
                        break;
                    default:
                        usage(1, "Invalid argument(s) specified");
                        break;
                }
            }
        }
        else
        {
            /* other arguments */
            if(NULL == pattern)
            {
                pattern = arg;
            }
            else if(NULL == rootDir)
            {
                rootDir = arg;
            }
            else
            {
                usage(1, "Invalid argument(s) specified");
            }
        }
    }

        if( NULL != password &&
                (       NULL == host ||
                        NULL == username))
        {
                usage(1, "Must specify host and username if specifying password");
        }

        if( NULL != username &&
                NULL == host)
        {
                usage(1, "Must specify host if specifying username");
        }

        if( NULL != host &&
                bAllHardDrives)
        {
                usage(1, "-h flag meaningless to FTP searches");
        }

    if( NULL != host &&
                NULL == rootDir)
    {
                usage(1, "Must specify a root directory for FTP searches");
    }

#if defined(_MSC_VER) && \
    defined(_DEBUG)
    _CrtMemCheckpoint(&memState);
#endif /* _MSC_VER && _MSC_VER */

    // Search for files if neither files or directories specified
    //
    // Even though this is not necessary, because the recls API provides the
    // same interpretation, it's best to be explicit.
    if(0 == (flags & (RECLS_F_FILES | RECLS_F_DIRECTORIES)))
    {
        flags |= RECLS_F_FILES;
    }

    if(NULL == pattern)
    {
        pattern = recls::Recls_GetWildcardsAll();
    }

    if(NULL == rootDir)
    {
        rootDir = ".";
    }

    if(bAllHardDrives)
    {
        reclstl::basic_root_sequence<recls_char_t>                  roots;
        reclstl::basic_root_sequence<recls_char_t>::const_iterator  begin   =   roots.begin();
        reclstl::basic_root_sequence<recls_char_t>::const_iterator  end     =   roots.end();

        for(; begin != end; ++begin)
        {
            totalFound += processDirectory(host, username, password, *begin, pattern, flags, bSuccinct);
        }
    }
    else
    {
        totalFound = processDirectory(host, username, password, rootDir, pattern, flags, bSuccinct);
    }

    fprintf(stdout, "Total found: %d\n", totalFound);

#if defined(_MSC_VER) && \
    defined(_DEBUG)
    _CrtMemDumpAllObjectsSince(&memState);
#endif /* _MSC_VER && _MSC_VER */

    return iRet;
}

/* 
 * Function implementations
 */

void usage(int bExit, char const *reason)
{
    cerr << "recls STL Test Program:" << endl << endl;

        if(NULL != reason)
        {
                fprintf(stderr, "  Error: %s\n\n", reason);
        }

    cerr << "Usage: STL [-d] [-f] [-h] [-p] [-R] [-s] [-H<host>] [-U<username>] [-P<password>] [<pattern>] [<root-dir>]" << endl;
    cerr << "\t-R               -   does not recurse; recursive search is the default" << endl;
    cerr << "\t-p               -   evaluate and display directory parts" << endl;
    cerr << "\t-d               -   search for directories" << endl;
    cerr << "\t-f               -   search for files (this is the default, if -d is not specified" << endl;
    cerr << "\t-h               -   searches from hard drive roots. (Ignore <root-dir>.)" << endl;
    cerr << "\t-s               -   succinct; shows only the path" << endl;
        cerr << "\t-H<host>         -   performs an FTP search on the given host" << endl;
        cerr << "\t-U<username>     -   username to use to log on to <host>" << endl;
        cerr << "\t-P<password>     -   password to use to log on to <host>" << endl;
    cerr << "\t<pattern>        -   search pattern, e.g. \"*.cpp\"; default is to search for all files" << endl;
    cerr << "\t<root-dir>       -   root directory of search; default is current working directory" << endl;

    if(bExit)
    {
        exit(EXIT_FAILURE);
    }
}


int processDirectory(char const *host, char const *username, char const *password, char const *rootDir, char const *pattern, long flags, int bSuccinct)
{
    typedef reclstl::basic_search_sequence<recls_char_t>    sequence_t;

    int         totalFound      =   0;
#if defined(RECLS_API_FTP)
    sequence_t  search(host, username, password, rootDir, pattern, flags);
#else /* ? RECLS_API_FTP */
        STLSOFT_SUPPRESS_UNUSED(host);
        STLSOFT_SUPPRESS_UNUSED(username);
        STLSOFT_SUPPRESS_UNUSED(password);
    sequence_t  search(rootDir, pattern, flags);
#endif /* RECLS_API_FTP */

    sequence_t::const_iterator    begin   =   search.begin();
    sequence_t::const_iterator    end     =   search.end();

    for(; begin != end; ++begin)
    {
        using reclstl::string_t;

        ++totalFound;

        sequence_t::value_type    fileEntry   =   *begin;

#ifdef RECLS_PLATFORM_API_WIN32
        recls_char_t            drive       =   fileEntry.get_drive();
#endif /* RECLS_PLATFORM_API_WIN32 */
        string_t                path        =   fileEntry.get_path();
        string_t                dir         =   fileEntry.get_directory();
        string_t                dirPath     =   fileEntry.get_directory_path();
        string_t                file        =   fileEntry.get_file();
        string_t                fileName    =   fileEntry.get_filename();
        string_t                fileExt     =   fileEntry.get_fileext();

        string_t                pathCheck;
        string_t                dirCheck;
        string_t                fileCheck;

        cout << "  " << path << endl;
        if(!bSuccinct)
        {
            int off = 0;

            cout << "  " << dirPath << endl;
#ifdef RECLS_PLATFORM_API_WIN32
                        if(0 != drive)
                        {
                                if(isupper(path[0]))
                                {
                                        drive = (recls_char_t)toupper(drive);
                                }
                                else
                                {
                                        drive = (recls_char_t)tolower(drive);
                                }
                                cout << "  " << drive << endl;
                                pathCheck += drive;
                                pathCheck += ':';

                                off += 2;
                        }
#endif /* RECLS_PLATFORM_API_WIN32 */
            cout << "  " << setw(off) << dir << endl;

            typedef sequence_t::value_type::directory_parts_type  directory_parts_type;

            if((flags & RECLS_F_DIRECTORY_PARTS) == RECLS_F_DIRECTORY_PARTS)
            {
                directory_parts_type    dirParts    =   fileEntry.get_directory_parts();
                int                     i;

                directory_parts_type::iterator  begin   =   dirParts.begin();
                directory_parts_type::iterator  end     =   dirParts.end();

                for(i = 0; begin != end; ++begin, ++i)
                {
                    string_t    dirPart =   *begin;

                    off += dirPart.length();
                    cout << "  " << setw(off) << dirPart << setw(1) << endl;

                    pathCheck += dirPart;
                    dirCheck += dirPart;
                }
            }
            else
            {
                off += dir.length();
                pathCheck += dir;
            }

            off += file.length();
            cout << "  " << setw(off) << file << setw(1) << endl;
            if(fileExt.length() > 0)
            {
                cout << "  " << setw(off - (1 + fileExt.length())) << fileName << setw(1) << endl;
                cout << "  " << setw(off) << fileExt << setw(1) << endl;
            }
            else
            {
                cout << "  " << setw(off) << fileName << setw(1) << endl;
            }

            fileCheck = fileName;
            if(0 < fileExt.length())
            {
                fileCheck += '.';
                fileCheck += fileExt;
            }

            pathCheck += file;

            // Now validate the components
            recls_assert(path == pathCheck);
            if(path != pathCheck)
            {
                cerr << "Path is different from path components" << endl 
                                         << "\tpath:  \"" << path << "\"" << endl 
                                         << "\tparts: \"" << pathCheck << "\"" << endl
                                         << endl;

                abort();
            }
#ifdef RECLS_PLATFORM_API_WIN32
            recls_assert(NULL != host || (dirPath[0] == drive && dir == dirPath.c_str() + 2));
            recls_assert(NULL == host || dir == dirPath);
            if( (       NULL == host &&
                                        (       dirPath[0] != drive ||
                                                dir != dirPath.c_str() + 2)) ||
                                (       NULL != host &&
                                        dir != dirPath))
#else
            recls_assert(dirPath == dir);
            if(dirPath != dir)
#endif /* RECLS_PLATFORM_API_WIN32 */
            {
                cerr << "DirectoryPath is different from Directory" << endl 
                                         << "\tdirPath: \"" << dirPath << "\"" << endl
                                         << "\tdir:     \"" << dir << "\"" << endl
                                         << endl;

                abort();
            }
            if((flags & RECLS_F_DIRECTORY_PARTS) == RECLS_F_DIRECTORY_PARTS)
            {
                recls_assert(dir == dirCheck);
                if(dir != dirCheck)
                {
                    cerr << "Directory is different from directory components" << endl << "\tpath:  " << dir << "" << endl << "\tparts: " << dirCheck << endl << endl;

                    abort();
                }
            }
            recls_assert(file == fileCheck);
            if(file != fileCheck)
            {
                cerr << "File is different from file components" << endl << "\tpath:  " << "%s" << "" << endl << "\tparts: " << "%s" << endl << endl;

                abort();
            }

            if(fileEntry.is_readonly())
            {
                cout << "    - Read-only" << endl;
            }
            if(fileEntry.is_directory())
            {
                cout << "    - Directory" << endl;
            }
            else
            {
                cout << "    - File" << endl;
            }
            if(fileEntry.is_link())
            {
                cout << "    - Link" << endl;
            }
        }
    }

    return totalFound;
}

/* 
 * End of file
 */

WinForm.cs

This program uses the recls C# mapping classes, implementing a recursive search for a given pattern, and other flags, from a given directory

namespace CS
{
    using System;
    using System.Drawing;
    using System.Collections;
    using System.ComponentModel;
    using System.Windows.Forms;
    using System.Data;
    using recls;

    public class WinForm : System.Windows.Forms.Form
    {
        private System.ComponentModel.Container components = null;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.TextBox searchRoot;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.TextBox pattern;
        private System.Windows.Forms.Button btnSearch;
        private System.Windows.Forms.ListView listFiles;
        private System.Windows.Forms.ListView listProperties;
        private System.Windows.Forms.Label label4;
        private System.Windows.Forms.ListBox listDirectoryParts;
        private System.Windows.Forms.CheckBox chkRecursive;
        private System.Windows.Forms.CheckBox chkDirectoryParts;
        private System.Windows.Forms.Label lblDirectoryParts;
        private System.Windows.Forms.ProgressBar progbar;
        private System.Windows.Forms.RadioButton rbtnFiles;
        private System.Windows.Forms.RadioButton rbtnDirectories;
        private System.Windows.Forms.RadioButton rbtnBoth;
                private System.Windows.Forms.Label label5;
                private System.Windows.Forms.Label label6;
                private System.Windows.Forms.Label label7;
                private System.Windows.Forms.TextBox host;
                private System.Windows.Forms.TextBox username;
                private System.Windows.Forms.TextBox password;
        private System.Windows.Forms.Label label3;

        public WinForm()
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

            //
            // TODO: Add any constructor code after InitializeComponent call
            //
        }

        protected override void Dispose (bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code
        private void InitializeComponent()
        {
                        this.label1 = new System.Windows.Forms.Label();
                        this.searchRoot = new System.Windows.Forms.TextBox();
                        this.label2 = new System.Windows.Forms.Label();
                        this.pattern = new System.Windows.Forms.TextBox();
                        this.btnSearch = new System.Windows.Forms.Button();
                        this.label3 = new System.Windows.Forms.Label();
                        this.listFiles = new System.Windows.Forms.ListView();
                        this.listProperties = new System.Windows.Forms.ListView();
                        this.label4 = new System.Windows.Forms.Label();
                        this.lblDirectoryParts = new System.Windows.Forms.Label();
                        this.listDirectoryParts = new System.Windows.Forms.ListBox();
                        this.chkRecursive = new System.Windows.Forms.CheckBox();
                        this.chkDirectoryParts = new System.Windows.Forms.CheckBox();
                        this.progbar = new System.Windows.Forms.ProgressBar();
                        this.rbtnFiles = new System.Windows.Forms.RadioButton();
                        this.rbtnDirectories = new System.Windows.Forms.RadioButton();
                        this.rbtnBoth = new System.Windows.Forms.RadioButton();
                        this.label5 = new System.Windows.Forms.Label();
                        this.host = new System.Windows.Forms.TextBox();
                        this.label6 = new System.Windows.Forms.Label();
                        this.username = new System.Windows.Forms.TextBox();
                        this.label7 = new System.Windows.Forms.Label();
                        this.password = new System.Windows.Forms.TextBox();
                        this.SuspendLayout();
                        // 
                        // label1
                        // 
                        this.label1.Location = new System.Drawing.Point(8, 48);
                        this.label1.Name = "label1";
                        this.label1.Size = new System.Drawing.Size(100, 16);
                        this.label1.TabIndex = 6;
                        this.label1.Text = "Search &root:";
                        // 
                        // searchRoot
                        // 
                        this.searchRoot.Location = new System.Drawing.Point(112, 48);
                        this.searchRoot.Name = "searchRoot";
                        this.searchRoot.Size = new System.Drawing.Size(632, 20);
                        this.searchRoot.TabIndex = 7;
                        this.searchRoot.Text = "";
                        // 
                        // label2
                        // 
                        this.label2.Location = new System.Drawing.Point(8, 88);
                        this.label2.Name = "label2";
                        this.label2.Size = new System.Drawing.Size(100, 16);
                        this.label2.TabIndex = 8;
                        this.label2.Text = "&Pattern:";
                        // 
                        // pattern
                        // 
                        this.pattern.Location = new System.Drawing.Point(112, 80);
                        this.pattern.Name = "pattern";
                        this.pattern.TabIndex = 9;
                        this.pattern.Text = "*.*";
                        // 
                        // btnSearch
                        // 
                        this.btnSearch.Location = new System.Drawing.Point(664, 80);
                        this.btnSearch.Name = "btnSearch";
                        this.btnSearch.Size = new System.Drawing.Size(80, 23);
                        this.btnSearch.TabIndex = 15;
                        this.btnSearch.Text = "&Search";
                        this.btnSearch.Click += new System.EventHandler(this.btnSearch_Click);
                        // 
                        // label3
                        // 
                        this.label3.Location = new System.Drawing.Point(8, 120);
                        this.label3.Name = "label3";
                        this.label3.Size = new System.Drawing.Size(100, 16);
                        this.label3.TabIndex = 16;
                        this.label3.Text = "F&iles:";
                        // 
                        // listFiles
                        // 
                        this.listFiles.Location = new System.Drawing.Point(8, 136);
                        this.listFiles.MultiSelect = false;
                        this.listFiles.Name = "listFiles";
                        this.listFiles.Size = new System.Drawing.Size(384, 368);
                        this.listFiles.TabIndex = 17;
                        this.listFiles.View = System.Windows.Forms.View.Details;
                        this.listFiles.SelectedIndexChanged += new System.EventHandler(this.listFiles_SelectedIndexChanged);
                        // 
                        // listProperties
                        // 
                        this.listProperties.Location = new System.Drawing.Point(400, 136);
                        this.listProperties.Name = "listProperties";
                        this.listProperties.Size = new System.Drawing.Size(344, 224);
                        this.listProperties.TabIndex = 19;
                        this.listProperties.View = System.Windows.Forms.View.Details;
                        // 
                        // label4
                        // 
                        this.label4.Location = new System.Drawing.Point(408, 120);
                        this.label4.Name = "label4";
                        this.label4.Size = new System.Drawing.Size(100, 16);
                        this.label4.TabIndex = 18;
                        this.label4.Text = "Pr&operties";
                        // 
                        // lblDirectoryParts
                        // 
                        this.lblDirectoryParts.Location = new System.Drawing.Point(400, 368);
                        this.lblDirectoryParts.Name = "lblDirectoryParts";
                        this.lblDirectoryParts.Size = new System.Drawing.Size(120, 16);
                        this.lblDirectoryParts.TabIndex = 20;
                        this.lblDirectoryParts.Text = "Directory par&ts:";
                        // 
                        // listDirectoryParts
                        // 
                        this.listDirectoryParts.Location = new System.Drawing.Point(400, 384);
                        this.listDirectoryParts.Name = "listDirectoryParts";
                        this.listDirectoryParts.Size = new System.Drawing.Size(344, 121);
                        this.listDirectoryParts.TabIndex = 21;
                        // 
                        // chkRecursive
                        // 
                        this.chkRecursive.Checked = true;
                        this.chkRecursive.CheckState = System.Windows.Forms.CheckState.Checked;
                        this.chkRecursive.Location = new System.Drawing.Point(224, 88);
                        this.chkRecursive.Name = "chkRecursive";
                        this.chkRecursive.Size = new System.Drawing.Size(96, 16);
                        this.chkRecursive.TabIndex = 10;
                        this.chkRecursive.Text = "Recursi&ve";
                        // 
                        // chkDirectoryParts
                        // 
                        this.chkDirectoryParts.Checked = true;
                        this.chkDirectoryParts.CheckState = System.Windows.Forms.CheckState.Checked;
                        this.chkDirectoryParts.Location = new System.Drawing.Point(328, 88);
                        this.chkDirectoryParts.Name = "chkDirectoryParts";
                        this.chkDirectoryParts.Size = new System.Drawing.Size(104, 16);
                        this.chkDirectoryParts.TabIndex = 11;
                        this.chkDirectoryParts.Text = "Directory P&arts";
                        // 
                        // progbar
                        // 
                        this.progbar.Location = new System.Drawing.Point(8, 512);
                        this.progbar.Name = "progbar";
                        this.progbar.Size = new System.Drawing.Size(736, 16);
                        this.progbar.TabIndex = 11;
                        // 
                        // rbtnFiles
                        // 
                        this.rbtnFiles.Appearance = System.Windows.Forms.Appearance.Button;
                        this.rbtnFiles.Checked = true;
                        this.rbtnFiles.Location = new System.Drawing.Point(440, 80);
                        this.rbtnFiles.Name = "rbtnFiles";
                        this.rbtnFiles.Size = new System.Drawing.Size(48, 24);
                        this.rbtnFiles.TabIndex = 12;
                        this.rbtnFiles.TabStop = true;
                        this.rbtnFiles.Text = "&Files";
                        // 
                        // rbtnDirectories
                        // 
                        this.rbtnDirectories.Appearance = System.Windows.Forms.Appearance.Button;
                        this.rbtnDirectories.Location = new System.Drawing.Point(496, 80);
                        this.rbtnDirectories.Name = "rbtnDirectories";
                        this.rbtnDirectories.Size = new System.Drawing.Size(72, 24);
                        this.rbtnDirectories.TabIndex = 13;
                        this.rbtnDirectories.Text = "&Directories";
                        // 
                        // rbtnBoth
                        // 
                        this.rbtnBoth.Appearance = System.Windows.Forms.Appearance.Button;
                        this.rbtnBoth.Location = new System.Drawing.Point(576, 80);
                        this.rbtnBoth.Name = "rbtnBoth";
                        this.rbtnBoth.Size = new System.Drawing.Size(48, 24);
                        this.rbtnBoth.TabIndex = 14;
                        this.rbtnBoth.Text = "&Both";
                        // 
                        // label5
                        // 
                        this.label5.Location = new System.Drawing.Point(8, 16);
                        this.label5.Name = "label5";
                        this.label5.Size = new System.Drawing.Size(96, 23);
                        this.label5.TabIndex = 0;
                        this.label5.Text = "&Host:";
                        // 
                        // host
                        // 
                        this.host.Location = new System.Drawing.Point(112, 16);
                        this.host.Name = "host";
                        this.host.Size = new System.Drawing.Size(128, 20);
                        this.host.TabIndex = 1;
                        this.host.Text = "";
                        // 
                        // label6
                        // 
                        this.label6.Location = new System.Drawing.Point(248, 16);
                        this.label6.Name = "label6";
                        this.label6.TabIndex = 2;
                        this.label6.Text = "&Username:";
                        // 
                        // username
                        // 
                        this.username.Location = new System.Drawing.Point(360, 16);
                        this.username.Name = "username";
                        this.username.Size = new System.Drawing.Size(144, 20);
                        this.username.TabIndex = 3;
                        this.username.Text = "";
                        // 
                        // label7
                        // 
                        this.label7.Location = new System.Drawing.Point(512, 16);
                        this.label7.Name = "label7";
                        this.label7.Size = new System.Drawing.Size(80, 23);
                        this.label7.TabIndex = 4;
                        this.label7.Text = "&Password:";
                        // 
                        // password
                        // 
                        this.password.Location = new System.Drawing.Point(600, 16);
                        this.password.Name = "password";
                        this.password.PasswordChar = '*';
                        this.password.Size = new System.Drawing.Size(144, 20);
                        this.password.TabIndex = 5;
                        this.password.Text = "";
                        // 
                        // WinForm
                        // 
                        this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
                        this.ClientSize = new System.Drawing.Size(752, 531);
                        this.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                                                                                                                  this.password,
                                                                                                                                                  this.label7,
                                                                                                                                                  this.username,
                                                                                                                                                  this.label6,
                                                                                                                                                  this.host,
                                                                                                                                                  this.label5,
                                                                                                                                                  this.rbtnFiles,
                                                                                                                                                  this.progbar,
                                                                                                                                                  this.chkDirectoryParts,
                                                                                                                                                  this.chkRecursive,
                                                                                                                                                  this.listDirectoryParts,
                                                                                                                                                  this.lblDirectoryParts,
                                                                                                                                                  this.label4,
                                                                                                                                                  this.listProperties,
                                                                                                                                                  this.listFiles,
                                                                                                                                                  this.label3,
                                                                                                                                                  this.btnSearch,
                                                                                                                                                  this.pattern,
                                                                                                                                                  this.label2,
                                                                                                                                                  this.searchRoot,
                                                                                                                                                  this.label1,
                                                                                                                                                  this.rbtnDirectories,
                                                                                                                                                  this.rbtnBoth});
                        this.Name = "WinForm";
                        this.Text = "recls C# mapping test";
                        this.Load += new System.EventHandler(this.WinForm_Load);
                        this.ResumeLayout(false);

                }
        #endregion

        [STAThread]
        static void Main() 
        {
            Application.Run(new WinForm());
        }
        
        private void btnSearch_Click(object sender, System.EventArgs e)
        {
            progbar.Maximum = 1000;

            RECLS_FLAG  flags = 0;

            if(rbtnBoth.Checked)
            {
                flags |= RECLS_FLAG.RECLS_F_DIRECTORIES | RECLS_FLAG.RECLS_F_FILES;
            }
            else if(rbtnFiles.Checked)
            {
                flags |= RECLS_FLAG.RECLS_F_FILES;
            }
            else if(rbtnDirectories.Checked)
            {
                flags |= RECLS_FLAG.RECLS_F_DIRECTORIES;
            }

            if(chkRecursive.Checked)
            {
                flags |= RECLS_FLAG.RECLS_F_RECURSIVE;
            }

            if(chkDirectoryParts.Checked)
            {
                flags |= RECLS_FLAG.RECLS_F_DIRECTORY_PARTS;
            }

            listDirectoryParts.Enabled = chkDirectoryParts.Checked;
            lblDirectoryParts.Enabled = chkDirectoryParts.Checked;

                        Search  fs;

                        if(host.Text.Length > 0)
                        {
                                fs = new FtpSearch(host.Text, username.Text, password.Text, searchRoot.Text, pattern.Text, flags);
                        }
                        else
                        {
                                fs = new FileSearch(searchRoot.Text, pattern.Text, flags);
                        }

            listFiles.Items.Clear();
            listProperties.Items.Clear();
            listDirectoryParts.Items.Clear();

            foreach(FileEntry fe in fs)
            {
                ListViewItem    lvi = new ListViewItem(fe.Path);

                lvi.Tag = fe;

                listFiles.Items.Add(lvi);

                if(1 + progbar.Value == progbar.Maximum)
                {
                    progbar.Value = 0;
                }
                else
                {
                    progbar.Value = 1 + progbar.Value;
                }
                progbar.Update();

                listFiles.Update();
            }

            progbar.Value = 0;
        }

        private void WinForm_Load(object sender, System.EventArgs e)
        {
            int cx;
            
            cx = listFiles.Width - 4;
            listFiles.Columns.Add("Filename", cx, HorizontalAlignment.Left);

            cx = listProperties.Width - 4;
            listProperties.Columns.Add("Property", cx * 2 / 5, HorizontalAlignment.Left);
            listProperties.Columns.Add("Value", cx * 3 / 5, HorizontalAlignment.Left);
        }

        private void listFiles_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            ListView.SelectedListViewItemCollection items = listFiles.SelectedItems;

            if(items.Count == 1)
            {
                PopulateProperties((FileEntry)items[0].Tag);
            }
        }

        private string TranslateEntryAttributes(FileEntry fe)
        {
            string  s   =   "";

            if(fe.IsDirectory)
            {
                if(s.Length > 0)
                {
                    s += " ";
                }
                s += "[Directory]";
            }

            if(fe.IsLink)
            {
                if(s.Length > 0)
                {
                    s += " ";
                }
                s += "[Link]";
            }

            if(fe.IsReadOnly)
            {
                if(s.Length > 0)
                {
                    s += " ";
                }
                s += "[Read only]";
            }

            return s;
        }

        private void PopulateProperties(FileEntry entry)
        {
            listProperties.Items.Clear();
            listDirectoryParts.Items.Clear();

            listProperties.Items.Add("Path").SubItems.Add(entry.Path);
            listProperties.Items.Add("Drive").SubItems.Add(entry.Drive.ToString());
            listProperties.Items.Add("Directory").SubItems.Add(entry.Directory);
            listProperties.Items.Add("DirectoryPath").SubItems.Add(entry.DirectoryPath);
            listProperties.Items.Add("File").SubItems.Add(entry.File);
            listProperties.Items.Add("ShortFile").SubItems.Add(entry.ShortFile);
            listProperties.Items.Add("FileName").SubItems.Add(entry.FileName);
            listProperties.Items.Add("FileExt").SubItems.Add(entry.FileExt);
            listProperties.Items.Add("CreationTime").SubItems.Add(entry.CreationTime.ToString());
            listProperties.Items.Add("ModificationTime").SubItems.Add(entry.ModificationTime.ToString());
            listProperties.Items.Add("LastAccessTime").SubItems.Add(entry.LastAccessTime.ToString());
            listProperties.Items.Add("LastStatusChangeTime").SubItems.Add(entry.LastStatusChangeTime.ToString());
            listProperties.Items.Add("Attributes").SubItems.Add(TranslateEntryAttributes(entry));

            foreach(string part in entry.DirectoryParts)
            {
                listDirectoryParts.Items.Add(part);
            }
        }
    }
}

COM.cpp

This program uses the recls COM mapping coclasses, implementing a recursive search for a given pattern, and other flags, from a given directory

/* 
 * File:        COM.cpp
 *
 * Purpose:     Implementation file for the COM project.
 *
 * Created:     19th December 2003
 * Updated:     8th June 2004
 *
 * Status:      Wizard-generated
 *
 * License:     (Licensed under the Synesis Software Open License)
 *
 *              Copyright (C) 1999-2004, Synesis Software Pty Ltd.
 *              All rights reserved.
 *
 *              www:        http://www.synesis.com.au/software
 *
 *              email:      software@synesis.com.au
 *
 *              This source code is placed into the public domain 2003
 *              by Synesis Software Pty Ltd. There are no restrictions
 *              whatsoever to your use of the software. 
 *
 *              This source code is provided by Synesis Software Pty Ltd "as is"
 *              and any warranties, whether expressed or implied, including, but
 *              not limited to, the implied warranties of merchantability and
 *              fitness for a particular purpose are disclaimed. In no event
 *              shall the Synesis Software Pty Ltd be liable for any direct,
 *              indirect, incidental, special, exemplary, or consequential
 *              damages (including, but not limited to, procurement of
 *              substitute goods or services; loss of use, data, or profits; or
 *              business interruption) however caused and on any theory of
 *              liability, whether in contract, strict liability, or tort
 *              (including negligence or otherwise) arising in any way out of
 *              the use of this software, even if advised of the possibility of
 *              such damage. 
 *
 *              Neither the name of Synesis Software Pty Ltd nor the names of
 *              any subdivisions, employees or agents of Synesis Software Pty
 *              Ltd, nor the names of any other contributors to this software
 *              may be used to endorse or promote products derived from this
 *              software without specific prior written permission. 
 *
 * 

#include <windows.h>
#include <stdio.h>
#if defined(__DMC__)
# include <iostream.h>
#else /* ? __DMC__ */
# include <iostream>
# include <iomanip>

using std::cout;
using std::wcout;
using std::cerr;
using std::endl;
#endif /* __DMC__ */
#include <stdlib.h>

#include <stlsoft.h>

#include <atlstl.h>

#include <comstl.h>
#include <comstl_enumerator_policies.h>
#include <comstl_initialisers.h>
#include <comstl_interface_cast.h>
#include <comstl_value_policies.h>
#include <comstl_enum_sequence.h>
#include <comstl_coll_sequence.h>

// This version of recls has been released at the same time as STLSoft 1.7.1 beta 3, in which
// comstl_method_cast.h resides in the "inprogress" sub-directory.
#include <inprogress/comstl_method_cast.h>
// 
// Once STLSoft 1.7.1 is released, this file will reside in the main directory, so you should
// comment out the include above, and uncomment the one below
//#include <comstl_method_cast.h>

#include <winstl.h>
#include <winstl_char_conversions.h>

#include <recls_com.h>
#include <recls_com_i.c>

#ifdef _MSC_VER
# include <CrtDbg.h>
#endif /* _MSC_VER */

//#define USE_ENUMVARIANT
#define USE_ENUMENTRY

/* 
 * Helper functions
 */

template<typename S>
S &operator <<(S &s, CComBSTR const &bstr)
{
    wchar_t const   *str = bstr;

    return s << str;
}

namespace comstl
{
    inline CComBSTR &transfer_resource(CComBSTR &r, BSTR v)
    {
        comstl_message_assert("Resource destination not empty!", NULL == r.m_str);
        r.m_str = v;

        return r;
    }
}

/* 
 * Forward declarations
 */

static void usage(int bExit, char const *reason);
int processRoot(IFileSearch *search, CComBSTR const &rootDir, CComBSTR const &pattern, long flags, int bSuccinct, int bFTP);
int processRoot(IFtpSearch *search, CComBSTR const &host, CComBSTR const &username, CComBSTR const &password, CComBSTR const &rootDir, CComBSTR const &pattern, long flags, int bSuccinct, int bFTP);
int processCollection(ISearchCollection *psc, long flags, int bSuccinct, int bFTP);

/* 
 * Main
 */

int main(int argc, char *argv[])
{
#if 0
    ::Sleep(100000);
#endif /* 0 */

#if defined(_MSC_VER) && \
    defined(_DEBUG)
    _CrtMemState    memState;
#endif /* _MSC_VER && _MSC_VER */
    int             iRet            =   0;
    int             i;
    int             totalFound      =   0;
    int             bAllHardDrives  =   false;
    char const      *host               =   NULL;
    char const      *username       =   NULL;
    char const      *password       =   NULL;
    char const      *pattern        =   NULL;
    char const      *rootDir        =   NULL;
    long            flags           =   RECLS_F_RECURSIVE;
    int             bSuccinct       =   false;

    for(i = 1; i < argc; ++i)
    {
        const char  *arg    =   argv[i];

        if(arg[0] == '-')
        {
            if(arg[1] == '-')
            {
                /* -- arguments */
            }
            else
            {
                /* - arguments */
                switch(arg[1])
                {
                    case    '?':
                        usage(1, NULL);
                        break;
                    case    'R':    /* Do not recurse */
                        flags &= ~(RECLS_F_RECURSIVE);
                        break;
                    case    'p':    /* Show directory parts */
                        flags |= RECLS_F_DIRECTORY_PARTS;
                        break;
                    case    'f':    /* Find files */
                        flags |= RECLS_F_FILES;
                        break;
                    case    'd':    /* Find directories */
                        flags |= RECLS_F_DIRECTORIES;
                        break;
                    case    'h':    /* Searches from hard drives */
                        bAllHardDrives = true;
                        break;
                    case    's':    /* Show only the full path; WHEREIS functionality */
                        bSuccinct = true;
                        break;
                    case    'H':    /* FTP host */
                        host = arg + 2;
                        break;
                    case    'U':    /* FTP username */
                        username = arg + 2;
                        break;
                    case    'P':    /* FTP password */
                        password = arg + 2;
                        break;
                    default:
                        usage(1, "Invalid argument(s) specified");
                        break;
                }
            }
        }
        else
        {
            /* other arguments */
            if(NULL == pattern)
            {
                pattern = arg;
            }
            else if(NULL == rootDir)
            {
                rootDir = arg;
            }
            else
            {
                usage(1, "Invalid argument(s) specified");
            }
        }
    }

        if( NULL != password &&
                (       NULL == host ||
                        NULL == username))
        {
                usage(1, "Must specify host and username if specifying password");
        }

        if( NULL != username &&
                NULL == host)
        {
                usage(1, "Must specify host if specifying username");
        }

        if( NULL != host &&
                bAllHardDrives)
        {
                usage(1, "-h flag meaningless to FTP searches");
        }

    if( NULL != host &&
                NULL == rootDir)
    {
                usage(1, "Must specify a root directory for FTP searches");
    }

#if defined(_MSC_VER) && \
    defined(_DEBUG)
    _CrtMemCheckpoint(&memState);
#endif /* _MSC_VER && _MSC_VER */

    // Search for files if neither files or directories specified
    //
    // Even though this is not necessary, because the recls API provides the
    // same interpretation, it's best to be explicit.
    if(0 == (flags & (RECLS_F_FILES | RECLS_F_DIRECTORIES)))
    {
        flags |= RECLS_F_FILES;
    }

#if 0
    if(NULL == pattern)
    {
        pattern = Recls_GetWildcardsAll();
    }
#endif /* 0 */

    if(NULL == rootDir)
    {
        rootDir = ".";
    }

        if(NULL != host)
        {
        IFtpSearch             *search;
        comstl::com_initialiser init;
        HRESULT                 hr      =   ::CoCreateInstance(CLSID_FileSearch, NULL, CLSCTX_ALL, IID_IFtpSearch, (void**)&search);

        if(FAILED(hr))
        {
            cerr << "Failed to load the recls COM server! Please check your installation" << endl;
        }
        else
        {
//            CComBSTR    bstrPattern = comstl::method_cast<CComBSTR>(search, &IFileSearch::get_WildcardsAll);

                        // The ATL conversion is not to be trusted for early versions, so we do it here.
                        winstl::a2w     host_(host);
                        winstl::a2w     username_(username);
                        winstl::a2w     password_(password);
                        winstl::a2w     rootDir_(rootDir);
                        winstl::a2w     pattern_(pattern);

                        CComBSTR        bstrHost(stlsoft::c_str_ptr(host));
                        CComBSTR        bstrUsername(stlsoft::c_str_ptr(username));
                        CComBSTR        bstrPassword(stlsoft::c_str_ptr(password));
                        CComBSTR        bstrRootDir(stlsoft::c_str_ptr(rootDir));
                        CComBSTR        bstrPattern(stlsoft::c_str_ptr(pattern));

                        if(0 == stlsoft::c_str_len(bstrPattern))
                        {
                                bstrPattern = L"*";
                        }

            totalFound = processRoot(search, bstrHost, bstrUsername, bstrPassword, bstrRootDir, bstrPattern, flags, bSuccinct, true);

            search->Release();
                }
        }
        else
    {
        IFileSearch             *search;
        comstl::com_initialiser init;
        HRESULT                 hr      =   ::CoCreateInstance(CLSID_FileSearch, NULL, CLSCTX_ALL, IID_IFileSearch, (void**)&search);

        if(FAILED(hr))
        {
            cerr << "Failed to load the recls COM server! Please check your installation" << endl;
        }
        else
        {
                        winstl::a2w     pattern_(pattern);
                        CComBSTR        bstrPattern(stlsoft::c_str_ptr(pattern));

                        if(0 == stlsoft::c_str_len(bstrPattern))
                        {
                                bstrPattern = comstl::method_cast<CComBSTR>(search, &IFileSearch::get_WildcardsAll);;
                        }

            if(bAllHardDrives)
            {
                LPUNKNOWN   punkRoots;

                hr = search->get_Roots(&punkRoots);

                if(SUCCEEDED(hr))
                {
                    typedef comstl::enumerator_sequence<IEnumString, LPOLESTR, comstl::LPOLESTR_policy> enum_sequence_t;

                    enum_sequence_t             roots(comstl::interface_cast_addref<LPENUMSTRING>(punkRoots), false);
                    enum_sequence_t::iterator   begin   =   roots.begin();
                    enum_sequence_t::iterator   end     =   roots.end();

                    for(; begin != end; ++begin)
                    {
                        totalFound += processRoot(search, *begin, bstrPattern, flags, bSuccinct, false);
                    }

                    punkRoots->Release();
                }
            }
            else
            {
                                winstl::a2w     rootDir_(rootDir);
                                CComBSTR        bstrRootDir(stlsoft::c_str_ptr(rootDir));

                totalFound = processRoot(search, bstrRootDir, bstrPattern, flags, bSuccinct, false);
            }

            search->Release();
        }
    }

    fprintf(stdout, "Total found: %d\n", totalFound);

#if defined(_MSC_VER) && \
    defined(_DEBUG)
    _CrtMemDumpAllObjectsSince(&memState);
#endif /* _MSC_VER && _MSC_VER */

    return iRet;
}

/* 
 * Function implementations
 */

void usage(int bExit, char const *reason)
{
    cerr << "recls COM (C++) Test Program: COM" << endl << endl;

        if(NULL != reason)
        {
                cerr << "  Error: " << reason << endl << endl;
        }

    cerr << "Usage: COM [-d] [-f] [-h] [-p] [-R] [-s] [-H<host>] [-U<username>] [-P<password>] [<pattern>] [<root-dir>]" << endl;
    cerr << "\t-R               -   does not recurse; recursive search is the default" << endl;
    cerr << "\t-p               -   evaluate and display directory parts" << endl;
    cerr << "\t-d               -   search for directories" << endl;
    cerr << "\t-f               -   search for files (this is the default, if -d is not specified" << endl;
    cerr << "\t-h               -   searches from hard drive roots. (Ignore <root-dir>.)" << endl;
    cerr << "\t-s               -   succinct; shows only the path" << endl;
        cerr << "\t-H<host>         -   performs an FTP search on the given host" << endl;
        cerr << "\t-U<username>     -   username to use to log on to <host>" << endl;
        cerr << "\t-P<password>     -   password to use to log on to <host>" << endl;
    cerr << "\t<pattern>        -   search pattern, e.g. \"*.cpp\"; default is to search for all files" << endl;
    cerr << "\t<root-dir>       -   root directory of search; default is current working directory" << endl;

    if(bExit)
    {
        exit(EXIT_FAILURE);
    }
}

int processRoot(IFtpSearch *search, CComBSTR const &host, CComBSTR const &username, CComBSTR const &password, CComBSTR const &rootDir, CComBSTR const &pattern, long flags, int bSuccinct, int bFTP)
{
    int         totalFound  =   0;
    IUnknown    *punkResults;
    HRESULT     hr          =   search->Search(host, username, password, rootDir, pattern, flags, &punkResults);

    if(SUCCEEDED(hr))
    {
        ISearchCollection   *psc = comstl::interface_cast_addref<ISearchCollection*>(punkResults);

        if(NULL != psc)
        {
                        totalFound = processCollection(psc, flags, bSuccinct, bFTP);

            psc->Release();
        }

        punkResults->Release();
    }

    return totalFound;
}

int processRoot(IFileSearch *search, CComBSTR const &rootDir, CComBSTR const &pattern, long flags, int bSuccinct, int bFTP)
{
    int         totalFound  =   0;
    IUnknown    *punkResults;
    HRESULT     hr          =   search->Search(rootDir, pattern, flags, &punkResults);

    if(SUCCEEDED(hr))
    {
        ISearchCollection   *psc = comstl::interface_cast_addref<ISearchCollection*>(punkResults);

        if(NULL != psc)
        {
                        totalFound = processCollection(psc, flags, bSuccinct, bFTP);

            psc->Release();
        }

        punkResults->Release();
    }

    return totalFound;
}

int processCollection(ISearchCollection *psc, long flags, int bSuccinct, int bFTP)
{
    int             totalFound      =   0;

#if defined(USE_ENUMVARIANT)
    typedef comstl::collection_sequence<    ISearchCollection
                                        ,   IEnumVARIANT
                                        ,   VARIANT
                                        ,   comstl::VARIANT_policy
                                        >           coll_seq_t;
#elif defined(USE_ENUMENTRY)
    typedef comstl::collection_sequence<    ISearchCollection
                                        ,   IEnumFileEntry
                                        ,   IFileEntry*
                                        ,   comstl::interface_policy<IFileEntry>
                                        >           coll_seq_t;
#else
# error Must specify USE_ENUMVARIANT or USE_ENUMENTRY
#endif /* 0 */

    coll_seq_t              collection(psc, true, bFTP ? 1 : 0);
    coll_seq_t::iterator    b   =   collection.begin();
    coll_seq_t::iterator    e   =   collection.end();

    for(; b != e; ++b)
    {
        ++totalFound;

#if defined(USE_ENUMVARIANT)
        IFileEntry  *pfe = comstl::interface_cast_addref<IFileEntry*>((*b).punkVal);
#elif defined(USE_ENUMENTRY)
        IFileEntry  *pfe = *b;
#else
# error Must specify USE_ENUMVARIANT or USE_ENUMENTRY
#endif /* 0 */

        CComBSTR    path                    =   comstl::method_cast<CComBSTR>(pfe, &IFileEntry::get_Path);
        OLECHAR     drive                   =   comstl::method_cast<OLECHAR>(pfe, &IFileEntry::get_Drive);
        CComBSTR    directory               =   comstl::method_cast<CComBSTR>(pfe, &IFileEntry::get_Directory);
        CComBSTR    directoryPath           =   comstl::method_cast<CComBSTR>(pfe, &IFileEntry::get_DirectoryPath);
        LPUNKNOWN   directoryParts          =   comstl::method_cast<LPUNKNOWN>(pfe, &IFileEntry::get_DirectoryParts);
        CComBSTR    file                    =   comstl::method_cast<CComBSTR>(pfe, &IFileEntry::get_File);
        CComBSTR    shortFile               =   comstl::method_cast<CComBSTR>(pfe, &IFileEntry::get_ShortFile);
        CComBSTR    fileName                =   comstl::method_cast<CComBSTR>(pfe, &IFileEntry::get_FileName);
        CComBSTR    fileExt                 =   comstl::method_cast<CComBSTR>(pfe, &IFileEntry::get_FileExt);
        DATE        creationTime            =   comstl::method_cast<DATE>(pfe, &IFileEntry::get_CreationTime);
        DATE        modificationTime        =   comstl::method_cast<DATE>(pfe, &IFileEntry::get_ModificationTime);
        DATE        lastAccessTime          =   comstl::method_cast<DATE>(pfe, &IFileEntry::get_LastAccessTime);
        DATE        lastStatusChangeTime    =   comstl::method_cast<DATE>(pfe, &IFileEntry::get_LastStatusChangeTime);
        long        size                    =   comstl::method_cast<long>(pfe, &IFileEntry::get_Size);
        BOOL        isReadOnly              =   comstl::method_cast<BOOL>(pfe, &IFileEntry::get_IsReadOnly);
        BOOL        isDirectory             =   comstl::method_cast<BOOL>(pfe, &IFileEntry::get_IsDirectory);

        wcout << L"  " << path << endl;

        if(!bSuccinct)
        {
            wcout << L"  " << directoryPath << endl;
            wcout << L"  " << (wchar_t const *)winstl::a2w((char const*)&drive, 1) << endl;
            wcout << L"    " << directory << endl;

            int off = 0;

            if( (flags & RECLS_F_DIRECTORY_PARTS) == RECLS_F_DIRECTORY_PARTS &&
                NULL != directoryParts)
            {
                typedef comstl::collection_sequence<    IDirectoryPartsCollection
                                                    ,   IEnumVARIANT
                                                    ,   VARIANT
                                                    ,   comstl::VARIANT_policy
                                                    ,   VARIANT const &
                                                    ,   comstl::forward_cloning_policy<IEnumVARIANT>
                                                    ,   2
                                                    >           parts_seq_t;

                parts_seq_t             dirParts(comstl::interface_cast_addref<IDirectoryPartsCollection*>(directoryParts), false);
                parts_seq_t::iterator   b   =   dirParts.begin();
                parts_seq_t::iterator   e   =   dirParts.end();

                for(; b != e; ++b)
                {
                    CComVariant vPart(*b);  vPart.ChangeType(VT_BSTR);
                    CComBSTR    dirPart(vPart.bstrVal);

                    off += dirPart.Length();
                    wcout << L"    " << std::setw(off) << dirPart << std::setw(1) << endl;
                }

                directoryParts->Release();
            }
            else
            {
                off += directory.Length();
            }

            off += file.Length();
            wcout << L"    " << std::setw(off) << file << std::setw(1) << endl;
            if(fileExt.Length() > 0)
            {
                wcout << L"    " << std::setw(off - (1 + fileExt.Length())) << fileName << std::setw(1) << endl;
                wcout << L"    " << std::setw(off) << fileExt << std::setw(1) << endl;
            }
            else
            {
                wcout << L"    " << std::setw(off) << fileName << std::setw(1) << endl;
            }

            if(isReadOnly)
            {
                wcout << L"    - Read-only" << endl;
            }
            if(isDirectory)
            {
                wcout << L"    - Directory" << endl;
            }
            else
            {
                wcout << L"    - File" << endl;
            }
        }

#if defined(USE_ENUMVARIANT)
        pfe->Release();
#endif /* USE_ENUMVARIANT */
    }

        return totalFound;
}


/* 
 * End of file
 */

VBClient.frm

This program uses the recls COM mapping coclasses, implementing a recursive search for a given pattern, and other flags, from a given directory

VERSION 5.00
Begin VB.Form Form1 
   BorderStyle     =   3  'Fixed Dialog
   Caption         =   "Form1"
   ClientHeight    =   7320
   ClientLeft      =   45
   ClientTop       =   360
   ClientWidth     =   11550
   LinkTopic       =   "Form1"
   MaxButton       =   0   'False
   MinButton       =   0   'False
   ScaleHeight     =   7320
   ScaleWidth      =   11550
   ShowInTaskbar   =   0   'False
   StartUpPosition =   3  'Windows Default
   Begin VB.ListBox lstDirectoryParts 
      Height          =   2010
      Left            =   6360
      TabIndex        =   15
      Top             =   5040
      Width           =   5055
   End
   Begin VB.ListBox lstProperties 
      Height          =   2790
      Left            =   6360
      TabIndex        =   13
      Top             =   1800
      Width           =   5055
   End
   Begin VB.OptionButton rdoBoth 
      Caption         =   "&Both"
      Height          =   375
      Left            =   8160
      Style           =   1  'Graphical
      TabIndex        =   11
      Top             =   720
      Width           =   975
   End
   Begin VB.OptionButton rdoDirectories 
      Caption         =   "&Directories"
      Height          =   375
      Left            =   7080
      Style           =   1  'Graphical
      TabIndex        =   10
      Top             =   720
      Width           =   975
   End
   Begin VB.OptionButton rdoFiles 
      Caption         =   "&Files"
      Height          =   375
      Left            =   6120
      Style           =   1  'Graphical
      TabIndex        =   9
      Top             =   720
      Width           =   855
   End
   Begin VB.CheckBox chkRecursive 
      Caption         =   "Recursi&ve"
      Height          =   375
      Left            =   3360
      TabIndex        =   8
      Top             =   720
      Width           =   1215
   End
   Begin VB.CheckBox chkDirParts 
      Caption         =   "Directory P&arts"
      Height          =   375
      Left            =   4680
      TabIndex        =   7
      Top             =   720
      Width           =   1335
   End
   Begin VB.TextBox txtPattern 
      Height          =   375
      Left            =   1320
      TabIndex        =   5
      Text            =   "*.*"
      Top             =   720
      Width           =   1935
   End
   Begin VB.ListBox lstFiles 
      Height          =   5325
      Left            =   120
      TabIndex        =   3
      Top             =   1800
      Width           =   6135
   End
   Begin VB.CommandButton btnSearch 
      Caption         =   "&Search"
      Height          =   375
      Left            =   10080
      TabIndex        =   2
      Top             =   600
      Width           =   1335
   End
   Begin VB.TextBox txtSearchRoot 
      Height          =   375
      Left            =   1320
      TabIndex        =   1
      Text            =   "."
      Top             =   240
      Width           =   10095
   End
   Begin VB.Label Label5 
      Caption         =   "Directory pa&rts:"
      Height          =   255
      Left            =   6360
      TabIndex        =   14
      Top             =   4680
      Width           =   1815
   End
   Begin VB.Label Label4 
      Caption         =   "P&roperties:"
      Height          =   255
      Left            =   6360
      TabIndex        =   12
      Top             =   1440
      Width           =   1575
   End
   Begin VB.Label Label3 
      Caption         =   "F&iles:"
      Height          =   255
      Left            =   120
      TabIndex        =   6
      Top             =   1440
      Width           =   1335
   End
   Begin VB.Label Label2 
      Caption         =   "&Pattern:"
      Height          =   255
      Left            =   120
      TabIndex        =   4
      Top             =   840
      Width           =   975
   End
   Begin VB.Label Label1 
      Caption         =   "Search &root:"
      Height          =   255
      Left            =   120
      TabIndex        =   0
      Top             =   240
      Width           =   1095
   End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False

Private g_index As Integer
Private g_entries As Collection

Private Sub btnSearch_Click()

    Dim fs As New RECLS_COMLib.FileSearch

    Dim searchRoot As String
    Dim pattern As String
    Dim flags As Long

    Dim srch As Object

    ' Reset the collection
    Set g_entries = New Collection
    g_index = 0

    searchRoot = txtSearchRoot.Text
    pattern = txtPattern.Text
    flags = 0

    If chkRecursive.Value Then
        flags = flags Or RECLS_FLAG.RECLS_F_RECURSIVE
    End If

    If chkDirParts.Value Then
        flags = flags Or RECLS_FLAG.RECLS_F_DIRECTORY_PARTS
    End If

    If rdoBoth.Value = True Then
        flags = flags Or RECLS_FLAG.RECLS_F_FILES
        flags = flags Or RECLS_FLAG.RECLS_F_DIRECTORIES
    ElseIf rdoDirectories = True Then
        flags = flags Or RECLS_FLAG.RECLS_F_DIRECTORIES
    ElseIf rdoFiles = True Then
        flags = flags Or RECLS_FLAG.RECLS_F_FILES
    Else
        flags = flags Or RECLS_FLAG.RECLS_F_FILES
    End If
    

    Set srch = fs.Search(searchRoot, pattern, flags)

    lstFiles.Clear
    lstProperties.Clear
    lstDirectoryParts.Clear
    For Each entry In srch
        lstFiles.AddItem (entry)
        lstFiles.ItemData(lstFiles.NewIndex) = g_index
        
        g_entries.Add entry, CStr(g_index)
        g_index = g_index + 1
    Next

End Sub

Private Sub Form_Load()

    chkRecursive.Value = 1
    rdoFiles.Value = True

End Sub

Private Sub lstFiles_Click()

    Dim entry As RECLS_COMLib.FileEntry
    Dim index As Integer
    Dim dirParts As Object

    index = lstFiles.ItemData(lstFiles.ListIndex)

    Set entry = g_entries.Item(CStr(index))

    ' Do the properties
    lstProperties.Clear
    lstProperties.AddItem ("Drive: " & entry.Drive)
    lstProperties.AddItem ("Directory: " & entry.Directory)
    lstProperties.AddItem ("DirectoryPath: " & entry.DirectoryPath)
    lstProperties.AddItem ("File: " & entry.File)
    lstProperties.AddItem ("ShortFile: " & entry.ShortFile)
    lstProperties.AddItem ("FileName: " & entry.FileName)
    lstProperties.AddItem ("FileExt: " & entry.FileExt)
    lstProperties.AddItem ("CreationTime: " & entry.CreationTime)
    lstProperties.AddItem ("ModificationTime: " & entry.ModificationTime)
    lstProperties.AddItem ("LastAccessTime: " & entry.LastAccessTime)
    lstProperties.AddItem ("LastStatusChangeTime: " & entry.LastStatusChangeTime)
    lstProperties.AddItem ("Size: " & entry.Size)

    ' Do the directory parts
    Set dirParts = entry.DirectoryParts

    lstDirectoryParts.Clear
    For Each dirPart In dirParts
        lstDirectoryParts.AddItem (dirPart)
    Next

End Sub

recls_test_1.d

This program uses the free API functions in the recls D mapping, implementing a recursive search for a given pattern, and other flags, from a given directory

/* 
 * File:        recls_test_1.d
 *
 * Purpose:     Test program for the D mapping of recls. (Now the std.recls 
 *              module in the D standard library). Test free-functions.
 *
 * Created      
 * Updated:     8th June 2004
 *
 * Status:      Wizard-generated
 *
 * License:     (Licensed under the Synesis Software Open License)
 *
 *              Copyright (C) 1999-2003, Synesis Software Pty Ltd.
 *              All rights reserved.
 *
 *              www:        http://www.synesis.com.au/software
 *
 *              email:      software@synesis.com.au
 *
 *              This source code is placed into the public domain 2003
 *              by Synesis Software Pty Ltd. There are no restrictions
 *              whatsoever to your use of the software. 
 *
 *              This source code is provided by Synesis Software Pty Ltd "as is"
 *              and any warranties, whether expressed or implied, including, but
 *              not limited to, the implied warranties of merchantability and
 *              fitness for a particular purpose are disclaimed. In no event
 *              shall the Synesis Software Pty Ltd be liable for any direct,
 *              indirect, incidental, special, exemplary, or consequential
 *              damages (including, but not limited to, procurement of
 *              substitute goods or services; loss of use, data, or profits; or
 *              business interruption) however caused and on any theory of
 *              liability, whether in contract, strict liability, or tort
 *              (including negligence or otherwise) arising in any way out of
 *              the use of this software, even if advised of the possibility of
 *              such damage. 
 *
 *              Neither the name of Synesis Software Pty Ltd nor the names of
 *              any subdivisions, employees or agents of Synesis Software Pty
 *              Ltd, nor the names of any other contributors to this software
 *              may be used to endorse or promote products derived from this
 *              software without specific prior written permission. 
 *
 */


import std.recls;
import std.string;
import std.c.stdio;
import std.c.stdlib;

int main(char[][] args)
{
    int                 iRet        =   0;
    int                 i;
    char[]              pattern     =   null;
    char[]              rootDir     =   null;
    hrecls_t            hSrch;
    recls_rc_t          rc;
    recls_uint32_t      flags       =   RECLS_FLAG.RECLS_F_RECURSIVE;
    int                 bSuccinct   =   false;

    for(i = 1; i < args.length; ++i)
    {
        char[]  arg = args[i];

        if(arg[0] == '-')
        {
            if(arg[1] == '-')
            {
                /* -- arguments */
            }
            else
            {
                /* - arguments */
                switch(arg[1])
                {
                    case    'R':    /* Do not recurse */
                        flags &= ~(RECLS_FLAG.RECLS_F_RECURSIVE);
                        break;
                    case    'p':    /* Show directory parts */
                        flags |= RECLS_FLAG.RECLS_F_DIRECTORY_PARTS;
                        break;
                    case    'f':    /* Find files */
                        flags |= RECLS_FLAG.RECLS_F_FILES;
                        break;
                    case    'd':    /* Find directories */
                        flags |= RECLS_FLAG.RECLS_F_DIRECTORIES;
                        break;
                    case    's':    /* Show only the full path; WHEREIS functionality */
                        bSuccinct = true;
                        break;
                    default:
                        usage(1);
                        break;
                }
            }
        }
        else
        {
            /* other arguments */
            if(null == pattern)
            {
                pattern = arg;
            }
            else if(null == rootDir)
            {
                rootDir = arg;
            }
            else
            {
                usage(1);
            }
        }
    }

    /* Search for files if neither files or directories specified/
     *
     * Even though this is not necessary, because the recls API provides the
     * same interpretation, it's best to be explicit.
     */
    if(0 == (flags & (RECLS_FLAG.RECLS_F_FILES | RECLS_FLAG.RECLS_F_DIRECTORIES)))
    {
        flags |= RECLS_FLAG.RECLS_F_FILES;
    }

    if(null == pattern)
    {
version(Windows)
{
        pattern = "*.*";
}
else
{
        pattern = "*";
}
    }

    if(null == rootDir)
    {
        rootDir = ".";
    }

    /* Initiate the search. */
    rc = Search_Create(rootDir, pattern, flags, hSrch);

    if(RECLS_FAILED(rc))
    {
        char[]  err =   Search_GetErrorString(rc);

        fprintf(stderr, "Failed to start search, with pattern \"%.*s\"; recls error: %.*s\n", pattern, err);
    }
    else
    {
        /* Iterate through the items, until done */
        recls_info_t    entry;

        rc = Search_GetEntry(hSrch, entry);

        for(; RECLS_SUCCEEDED(rc); rc = Search_GetNextEntry(hSrch, entry))
        {
            int                 i;
            int                 off;
            int                 extLen;
            int                 cDirParts;
            char[]              path        =   Search_GetEntryPath(entry);
version(Windows)
{
            char                drive       =   Search_GetEntryDrive(entry);

            // This complex dance is necessitated because string and ctype seem
            // unable to coexist (with v0.74, anyway)
            if(drive != path[0])
            {
                char    p0upper = toupper(path[0 .. 1])[0];
                char    p0lower = tolower(path[0 .. 1])[0];

                if(drive == p0upper)
                {
                    drive = p0lower;
                }
                else
                {
                    drive = p0upper;
                }
            }
}
            char[]              dir         =   Search_GetEntryDirectory(entry);
            char[]              dirPath     =   Search_GetEntryDirectoryPath(entry);
            char[]              file        =   Search_GetEntryFile(entry);
            char[]              fileName    =   Search_GetEntryFileName(entry);
            char[]              fileExt     =   Search_GetEntryFileExt(entry);

            char[]              pathCheck   =   new char[0];
            char[]              dirCheck    =   new char[0];
            char[]              fileCheck;
            recls_filesize_t    size        =   Search_GetEntrySize(entry);

version(Debug)
{
                recls_uint32_t  cBlocks;
                Search_OutstandingEntry(hSrch, &cBlocks);
                printf("\n%d outstanding blocks\n", cBlocks);
}

            printf("  %.*s\n", path);
            if(!bSuccinct)
            {
                printf("  %.*s\n", dirPath);
version(Windows)
{
                printf("  %c\n", drive);
                pathCheck ~= drive;
                pathCheck ~= ':';
}
                printf("    %.*s\n", dir);

                off = 0;
                if((flags & RECLS_FLAG.RECLS_F_DIRECTORY_PARTS) == RECLS_FLAG.RECLS_F_DIRECTORY_PARTS)
                {
                    char[][]    parts   =   Search_GetEntryDirectoryParts(entry);

                    foreach(char[] part; parts)
                    {
                        printf("    %*s", off, cast(char*)"");
                        printf("%.*s\n", part);
                        off += part.length;

                        pathCheck ~= part;
                        dirCheck ~= part;
                    }
                }
                else
                {
                    off += dir.length;
                    pathCheck ~= dir;
                }

                printf("    %*s%.*s\n", off, cast(char*)"", file);
                printf("    %*s%.*s\n", off, cast(char*)"", fileName);
                off     +=  file.length;
                extLen  =   fileExt.length;
                printf("    %*s%.*s\n", off - extLen, cast(char*)"", fileExt);
                fileCheck = fileName;
                if(0 < extLen)
                {
                    fileCheck ~= '.';
                    fileCheck ~= fileExt;
                }

                pathCheck ~= file;

                /* Now validate the components */
version(Windows)
{
                if(path != pathCheck)
                {
                    fprintf(stderr, "Path is different from path components\n\tpath:  %.*s\n\tpathCheck: %.*s\n\n", path, pathCheck);
                }
                assert(path == pathCheck);
}
else
{
                if(path != pathCheck)
                {
                    fprintf(stderr, "Path is different from path components\n\tpath:  %.*s\n\tpathCheck: %.*s\n\n", path, pathCheck);
                }
                assert(path == pathCheck);
}
version(Windows)
{
                if( dirPath[0] != drive ||
                    dir != dirPath[2 .. dirPath.length])
                {
                    fprintf(stderr, "DirectoryPath is different from Directory\n\tdirPath:  %.*s (%d)\n\tdir:      %c:%.*s (%d)\n\n", dirPath, dirPath.length - 2, drive, dir, dir.length);
                }
                assert(dirPath[0] == drive && dir == dirPath[2 .. dirPath.length]);
}
else
{
                if(dirPath != dir)
                {
                    fprintf(stderr, "DirectoryPath is different from Directory\n\tdirPath:  %.*s\n\tdir: %.*s\n\n", dirPath, dir);
                }
                assert(dirPath == dir);
}
                if((flags & RECLS_FLAG.RECLS_F_DIRECTORY_PARTS) == RECLS_FLAG.RECLS_F_DIRECTORY_PARTS)
                {
                    if(dir != dirCheck)
                    {
                        fprintf(stderr, "Directory is different from directory components\n\tdir:  %.*s\n\tdirCheck: %.*s\n\n", dir, dirCheck);
                    }
                    assert(dir == dirCheck);
                }
                if(file != fileCheck)
                {
                    fprintf(stderr, "File is different from file components\n\tfile:  %d:%.*s\n\tfileCheck: %d:%.*s\n\n", file.length, file, fileCheck.length, fileCheck);
                }
                assert(file == fileCheck);

                if(Search_IsEntryDirectory(entry))
                {
                    printf("    - Directory\n");
                }
                else
                {
                    printf("    - File\n");
                }
                if(Search_IsEntryReadOnly(entry))
                {
                    printf("    - Read-only\n");
                }
                if(Search_IsEntryLink(entry))
                {
                    printf("    - Link\n");
                }

                printf("    %lu\n", size);
            }

            Search_CloseEntry(entry);
        }

        if(rc != RECLS_RC_NO_MORE_DATA)
        {
            char[]  err =   Search_GetErrorString(rc);

            fprintf(stderr, "Search terminated prematurely; recls error: %.*s\n", err);
        }

        Search_Close(hSrch);
    }

    return iRet;
}

/* 
 * Function implementations
 */

void usage(int bExit)
{
    fprintf(stderr, "recls D Test Program: recls_test_1\n\n");
    fprintf(stderr, "Usage: recls_test_1 [-d] [-f] [-h] [-p] [-R] [-s] [-H<host>] [-U<username>] [-P<password>] [<pattern>] [<root-dir>]\n");
    fprintf(stderr, "\t-d               -   search for directories\n");
    fprintf(stderr, "\t-f               -   search for files. (default if neither f or d specified)\n");
    fprintf(stderr, "\t-p               -   include directory parts in search, and display\n");
    fprintf(stderr, "\t-R               -   does not recurse. (recursive search is the default)\n");
    fprintf(stderr, "\t-h               -   searches from hard drive roots. (Ignore <root-dir>.)\n");
    fprintf(stderr, "\t-s               -   succinct; shows only the path\n");
        fprintf(stderr, "\t-H<host>         -   performs an FTP search on the given host\n");
        fprintf(stderr, "\t-U<username>     -   username to use to log on to <host>\n");
        fprintf(stderr, "\t-P<password>     -   password to use to log on to <host>\n");
    fprintf(stderr, "\t<pattern>        -   search pattern, e.g. \"*.cpp\" (default is to search for all files)\n");
    fprintf(stderr, "\t<root-dir>       -   root directory of search; default is current working directory\n");

    if(bExit)
    {
        exit(1);
    }
}

/* 
 * End of file
 */

recls_test_2.d

This program uses the classes in the recls D mapping, implementing a recursive search for a given pattern, and other flags, from a given directory

/* 
 * File:        recls_test_1.d
 *
 * Purpose:     Test program for the D mapping of recls. (Now the std.recls 
 *              module in the D standard library). Test free-functions.
 *
 * Created      
 * Updated:     8th June 2004
 *
 * Status:      Wizard-generated
 *
 * License:     (Licensed under the Synesis Software Open License)
 *
 *              Copyright (C) 1999-2003, Synesis Software Pty Ltd.
 *              All rights reserved.
 *
 *              www:        http://www.synesis.com.au/software
 *
 *              email:      software@synesis.com.au
 *
 *              This source code is placed into the public domain 2003
 *              by Synesis Software Pty Ltd. There are no restrictions
 *              whatsoever to your use of the software. 
 *
 *              This source code is provided by Synesis Software Pty Ltd "as is"
 *              and any warranties, whether expressed or implied, including, but
 *              not limited to, the implied warranties of merchantability and
 *              fitness for a particular purpose are disclaimed. In no event
 *              shall the Synesis Software Pty Ltd be liable for any direct,
 *              indirect, incidental, special, exemplary, or consequential
 *              damages (including, but not limited to, procurement of
 *              substitute goods or services; loss of use, data, or profits; or
 *              business interruption) however caused and on any theory of
 *              liability, whether in contract, strict liability, or tort
 *              (including negligence or otherwise) arising in any way out of
 *              the use of this software, even if advised of the possibility of
 *              such damage. 
 *
 *              Neither the name of Synesis Software Pty Ltd nor the names of
 *              any subdivisions, employees or agents of Synesis Software Pty
 *              Ltd, nor the names of any other contributors to this software
 *              may be used to endorse or promote products derived from this
 *              software without specific prior written permission. 
 *
 */


import std.recls;
import std.string;
import std.c.stdio;
import std.c.stdlib;

int main(char[][] args)
{
    int                 iRet        =   0;
    int                 i;
    char[]              pattern     =   null;
    char[]              rootDir     =   null;
    hrecls_t            hSrch;
    recls_rc_t          rc;
    recls_uint32_t      flags       =   RECLS_FLAG.RECLS_F_RECURSIVE;
    int                 bSuccinct   =   false;

    for(i = 1; i < args.length; ++i)
    {
        char[]  arg = args[i];

        if(arg[0] == '-')
        {
            if(arg[1] == '-')
            {
                /* -- arguments */
            }
            else
            {
                /* - arguments */
                switch(arg[1])
                {
                    case    'R':    /* Do not recurse */
                        flags &= ~(RECLS_FLAG.RECLS_F_RECURSIVE);
                        break;
                    case    'p':    /* Show directory parts */
                        flags |= RECLS_FLAG.RECLS_F_DIRECTORY_PARTS;
                        break;
                    case    'f':    /* Find files */
                        flags |= RECLS_FLAG.RECLS_F_FILES;
                        break;
                    case    'd':    /* Find directories */
                        flags |= RECLS_FLAG.RECLS_F_DIRECTORIES;
                        break;
                    case    's':    /* Show only the full path; WHEREIS functionality */
                        bSuccinct = true;
                        break;
                    default:
                        usage(1);
                        break;
                }
            }
        }
        else
        {
            /* other arguments */
            if(null == pattern)
            {
                pattern = arg;
            }
            else if(null == rootDir)
            {
                rootDir = arg;
            }
            else
            {
                usage(1);
            }
        }
    }

    /* Search for files if neither files or directories specified/
     *
     * Even though this is not necessary, because the recls API provides the
     * same interpretation, it's best to be explicit.
     */
    if(0 == (flags & (RECLS_FLAG.RECLS_F_FILES | RECLS_FLAG.RECLS_F_DIRECTORIES)))
    {
        flags |= RECLS_FLAG.RECLS_F_FILES;
    }

    if(null == pattern)
    {
version(Windows)
{
        pattern = "*.*";
}
else
{
        pattern = "*";
}
    }

    if(null == rootDir)
    {
        rootDir = ".";
    }

    /* Initiate the search. */
    rc = Search_Create(rootDir, pattern, flags, hSrch);

    if(RECLS_FAILED(rc))
    {
        char[]  err =   Search_GetErrorString(rc);

        fprintf(stderr, "Failed to start search, with pattern \"%.*s\"; recls error: %.*s\n", pattern, err);
    }
    else
    {
        /* Iterate through the items, until done */
        recls_info_t    entry;

        rc = Search_GetEntry(hSrch, entry);

        for(; RECLS_SUCCEEDED(rc); rc = Search_GetNextEntry(hSrch, entry))
        {
            int                 i;
            int                 off;
            int                 extLen;
            int                 cDirParts;
            char[]              path        =   Search_GetEntryPath(entry);
version(Windows)
{
            char                drive       =   Search_GetEntryDrive(entry);

            // This complex dance is necessitated because string and ctype seem
            // unable to coexist (with v0.74, anyway)
            if(drive != path[0])
            {
                char    p0upper = toupper(path[0 .. 1])[0];
                char    p0lower = tolower(path[0 .. 1])[0];

                if(drive == p0upper)
                {
                    drive = p0lower;
                }
                else
                {
                    drive = p0upper;
                }
            }
}
            char[]              dir         =   Search_GetEntryDirectory(entry);
            char[]              dirPath     =   Search_GetEntryDirectoryPath(entry);
            char[]              file        =   Search_GetEntryFile(entry);
            char[]              fileName    =   Search_GetEntryFileName(entry);
            char[]              fileExt     =   Search_GetEntryFileExt(entry);

            char[]              pathCheck   =   new char[0];
            char[]              dirCheck    =   new char[0];
            char[]              fileCheck;
            recls_filesize_t    size        =   Search_GetEntrySize(entry);

version(Debug)
{
                recls_uint32_t  cBlocks;
                Search_OutstandingEntry(hSrch, &cBlocks);
                printf("\n%d outstanding blocks\n", cBlocks);
}

            printf("  %.*s\n", path);
            if(!bSuccinct)
            {
                printf("  %.*s\n", dirPath);
version(Windows)
{
                printf("  %c\n", drive);
                pathCheck ~= drive;
                pathCheck ~= ':';
}
                printf("    %.*s\n", dir);

                off = 0;
                if((flags & RECLS_FLAG.RECLS_F_DIRECTORY_PARTS) == RECLS_FLAG.RECLS_F_DIRECTORY_PARTS)
                {
                    char[][]    parts   =   Search_GetEntryDirectoryParts(entry);

                    foreach(char[] part; parts)
                    {
                        printf("    %*s", off, cast(char*)"");
                        printf("%.*s\n", part);
                        off += part.length;

                        pathCheck ~= part;
                        dirCheck ~= part;
                    }
                }
                else
                {
                    off += dir.length;
                    pathCheck ~= dir;
                }

                printf("    %*s%.*s\n", off, cast(char*)"", file);
                printf("    %*s%.*s\n", off, cast(char*)"", fileName);
                off     +=  file.length;
                extLen  =   fileExt.length;
                printf("    %*s%.*s\n", off - extLen, cast(char*)"", fileExt);
                fileCheck = fileName;
                if(0 < extLen)
                {
                    fileCheck ~= '.';
                    fileCheck ~= fileExt;
                }

                pathCheck ~= file;

                /* Now validate the components */
version(Windows)
{
                if(path != pathCheck)
                {
                    fprintf(stderr, "Path is different from path components\n\tpath:  %.*s\n\tpathCheck: %.*s\n\n", path, pathCheck);
                }
                assert(path == pathCheck);
}
else
{
                if(path != pathCheck)
                {
                    fprintf(stderr, "Path is different from path components\n\tpath:  %.*s\n\tpathCheck: %.*s\n\n", path, pathCheck);
                }
                assert(path == pathCheck);
}
version(Windows)
{
                if( dirPath[0] != drive ||
                    dir != dirPath[2 .. dirPath.length])
                {
                    fprintf(stderr, "DirectoryPath is different from Directory\n\tdirPath:  %.*s (%d)\n\tdir:      %c:%.*s (%d)\n\n", dirPath, dirPath.length - 2, drive, dir, dir.length);
                }
                assert(dirPath[0] == drive && dir == dirPath[2 .. dirPath.length]);
}
else
{
                if(dirPath != dir)
                {
                    fprintf(stderr, "DirectoryPath is different from Directory\n\tdirPath:  %.*s\n\tdir: %.*s\n\n", dirPath, dir);
                }
                assert(dirPath == dir);
}
                if((flags & RECLS_FLAG.RECLS_F_DIRECTORY_PARTS) == RECLS_FLAG.RECLS_F_DIRECTORY_PARTS)
                {
                    if(dir != dirCheck)
                    {
                        fprintf(stderr, "Directory is different from directory components\n\tdir:  %.*s\n\tdirCheck: %.*s\n\n", dir, dirCheck);
                    }
                    assert(dir == dirCheck);
                }
                if(file != fileCheck)
                {
                    fprintf(stderr, "File is different from file components\n\tfile:  %d:%.*s\n\tfileCheck: %d:%.*s\n\n", file.length, file, fileCheck.length, fileCheck);
                }
                assert(file == fileCheck);

                if(Search_IsEntryDirectory(entry))
                {
                    printf("    - Directory\n");
                }
                else
                {
                    printf("    - File\n");
                }
                if(Search_IsEntryReadOnly(entry))
                {
                    printf("    - Read-only\n");
                }
                if(Search_IsEntryLink(entry))
                {
                    printf("    - Link\n");
                }

                printf("    %lu\n", size);
            }

            Search_CloseEntry(entry);
        }

        if(rc != RECLS_RC_NO_MORE_DATA)
        {
            char[]  err =   Search_GetErrorString(rc);

            fprintf(stderr, "Search terminated prematurely; recls error: %.*s\n", err);
        }

        Search_Close(hSrch);
    }

    return iRet;
}

/* 
 * Function implementations
 */

void usage(int bExit)
{
    fprintf(stderr, "recls D Test Program: recls_test_1\n\n");
    fprintf(stderr, "Usage: recls_test_1 [-d] [-f] [-h] [-p] [-R] [-s] [-H<host>] [-U<username>] [-P<password>] [<pattern>] [<root-dir>]\n");
    fprintf(stderr, "\t-d               -   search for directories\n");
    fprintf(stderr, "\t-f               -   search for files. (default if neither f or d specified)\n");
    fprintf(stderr, "\t-p               -   include directory parts in search, and display\n");
    fprintf(stderr, "\t-R               -   does not recurse. (recursive search is the default)\n");
    fprintf(stderr, "\t-h               -   searches from hard drive roots. (Ignore <root-dir>.)\n");
    fprintf(stderr, "\t-s               -   succinct; shows only the path\n");
        fprintf(stderr, "\t-H<host>         -   performs an FTP search on the given host\n");
        fprintf(stderr, "\t-U<username>     -   username to use to log on to <host>\n");
        fprintf(stderr, "\t-P<password>     -   password to use to log on to <host>\n");
    fprintf(stderr, "\t<pattern>        -   search pattern, e.g. \"*.cpp\" (default is to search for all files)\n");
    fprintf(stderr, "\t<root-dir>       -   root directory of search; default is current working directory\n");

    if(bExit)
    {
        exit(1);
    }
}

/* 
 * End of file
 */

recls_test.java

This program uses the classes in the recls Java mapping, implementing a recursive search for a given pattern, and other flags, from a given directory

/* 
 * File:        recls_test.java
 *
 * Purpose:     Test file for the recls Java mapping.
 *
 * Created:     22nd November 2003
 * Updated:     3rd June 2004
 *
 * Status:      Wizard-generated
 *
 * License:     (Licensed under the Synesis Software Open License)
 *
 *              Copyright (C) 1999-2003, Synesis Software Pty Ltd.
 *              All rights reserved.
 *
 *              www:        http://www.synesis.com.au/software
 *
 *              email:      software@synesis.com.au
 *
 *              This source code is placed into the public domain 2003
 *              by Synesis Software Pty Ltd. There are no restrictions
 *              whatsoever to your use of the software. 
 *
 *              This source code is provided by Synesis Software Pty Ltd "as is"
 *              and any warranties, whether expressed or implied, including, but
 *              not limited to, the implied warranties of merchantability and
 *              fitness for a particular purpose are disclaimed. In no event
 *              shall the Synesis Software Pty Ltd be liable for any direct,
 *              indirect, incidental, special, exemplary, or consequential
 *              damages (including, but not limited to, procurement of
 *              substitute goods or services; loss of use, data, or profits; or
 *              business interruption) however caused and on any theory of
 *              liability, whether in contract, strict liability, or tort
 *              (including negligence or otherwise) arising in any way out of
 *              the use of this software, even if advised of the possibility of
 *              such damage. 
 *
 *              Neither the name of Synesis Software Pty Ltd nor the names of
 *              any subdivisions, employees or agents of Synesis Software Pty
 *              Ltd, nor the names of any other contributors to this software
 *              may be used to endorse or promote products derived from this
 *              software without specific prior written permission. 
 *
 */


import org.recls.Entry;
import org.recls.ReclsException;
import org.recls.Search;
import org.recls.FileSearch;
import org.recls.FtpSearch;

import java.util.Enumeration;

public class recls_test
{
    public static void main(String[] args)
    {
        int     i;
        String  host            =   null;
        String  username    =   null;
        String  password    =   null;
        String  pattern     =   null;
        String  rootDir     =   null;
        int     flags       =   Search.RECLS_F_RECURSIVE;
        boolean bSuccinct   =   false;

        for(i = 0; i < args.length; ++i)
        {
            String  arg = args[i];

            if(arg.charAt(0) == '-')
            {
                if(arg.charAt(1) == '-')
                {
                    /* -- arguments */
                }
                else
                {
                    /* - arguments */
                    switch(arg.charAt(1))
                    {
                        case    'R':    /* Do not recurse */
                            flags &= ~(Search.RECLS_F_RECURSIVE);
                            break;
                        case    'p':    /* Show directory parts */
                            flags |= Search.RECLS_F_DIRECTORY_PARTS;
                            break;
                        case    'f':    /* Find files */
                            flags |= Search.RECLS_F_FILES;
                            break;
                        case    'd':    /* Find directories */
                            flags |= Search.RECLS_F_DIRECTORIES;
                            break;
                        case    's':    /* Show only the full path; WHEREIS functionality */
                            bSuccinct = true;
                            break;
                        case    'H':
                            host = arg.substring(2);
                            break;
                        default:
                            usage(true);
                            break;
                    }
                }
            }
            else
            {
                /* other arguments */
                if(null == pattern)
                {
                    pattern = arg;
                }
                else if(null == rootDir)
                {
                    rootDir = arg;
                }
                else
                {
                    usage(true);
                }
            }
        }

        /* Search for files if neither files or directories specified/
         *
         * Even though this is not necessary, because the recls API provides the
         * same interpretation, it's best to be explicit.
         */
        if(0 == (flags & (Search.RECLS_F_FILES | Search.RECLS_F_DIRECTORIES)))
        {
            flags |= Search.RECLS_F_FILES;
        }

        try
        {
            int     total   =   0;
            Search  search;

                        if(null != host)
                        {
                                search  =       new FtpSearch(host, username, password, rootDir, pattern, flags);
                        }
                        else
                        {
                                search  =       new FileSearch(rootDir, pattern, flags);
                        }

            for(Enumeration en = search; en.hasMoreElements(); ++total)
            {
                Object  el  =   en.nextElement();

                System.out.println(el);

                if(!bSuccinct)
                {
                    Entry   entry   =   (Entry)el;

                    System.out.println("  Path:                  " + entry.getPath());
                    System.out.println("  Drive:                 " + entry.getDrive());
                    System.out.println("  Directory:             " + entry.getDirectory());
                    System.out.println("  DirectoryPath:         " + entry.getDirectoryPath());
                    if((flags & Search.RECLS_F_DIRECTORY_PARTS) == Search.RECLS_F_DIRECTORY_PARTS)
                    {
                        String[]    dirParts    =   entry.getDirectoryParts();
                        for(int j = 0; j < dirParts.length; ++j)
                        {
                            System.out.println("    " + dirParts[j]);
                        }
                    }
                    System.out.println("  File:                  " + entry.getFile());
                    System.out.println("  ShortFile:             " + entry.getShortFile());
                    System.out.println("  FileName:              " + entry.getFileName());
                    System.out.println("  FileExtL               " + entry.getFileExt());
                    System.out.println("  Size:                  " + entry.getSize());
                    System.out.println("  CreationTime:          " + entry.getCreationTime());
                    System.out.println("  ModificationTime:      " + entry.getModificationTime());
                    System.out.println("  LastAccessTime:        " + entry.getLastAccessTime());
                    System.out.println("  LastStatusChangeTime:  " + entry.getLastStatusChangeTime());
                    System.out.println("  isReadOnly:            " + entry.isReadOnly());
                    System.out.println("  isDirectory:           " + entry.isDirectory());
                    System.out.println("  isLink:                " + entry.isLink());
                }
            }

            search.close();

            System.out.println("  Total matched: " + total);
        }
        catch(ReclsException x)
        {
            System.out.println(x);
        }
    }

    private static void usage(boolean bExit)
    {
        System.err.println("recls Java Test Program: java_test\n");
        System.err.println("Usage: java java_test [-d] [-f] [-d] [-R] [-H<host>] [<pattern>] [<root-dir>]");
        System.err.println("\t-d               -   search for directories");
        System.err.println("\t-f               -   search for files. (default if neither f or d specified)");
        System.err.println("\t-H               -   search for files using FTP on the given <host>");
        System.err.println("\t-p               -   include directory parts in search, and display");
        System.err.println("\t-R               -   does not recurse. (recursive search is the default)");
        System.err.println("\t-s               -   succinct; shows only the path");
        System.err.println("\t<pattern>        -   search pattern, e.g. \"*.cpp\" (default is to search for all files)");
        System.err.println("\t<root-dir>       -   root directory of search; default is current working directory");

        if(bExit)
        {
            System.exit(1);
        }
    }
}


recls Library documentation © Synesis Software Pty Ltd, 2001-2004