//*****************************************************************************
// ListUpAllFiles.cpp : 指定のディレクトリ下(サブディレクトリも含む)の指定
//                      ファイルを全てリストアップする(複数パス指定可)
//*****************************************************************************

#include "stdafx.h"

#define MAXPARAMLEN             256
#define MAXMULTIPATHCOUNT       10  
#define DIRFUNCTIONBUFLEN       200*1024        // 200 KB

#define C_SPACE                 ' '
#define C_QUOT                  '"'

int ListUpAllFiles( char* ppath , char* bufp , int bufsize ) ;
int ListUpFiles( char* ppath , char* bufp , int bufsize ) ;
int GetMultiFileFirst( char* ppath , char* pfilepath ) ;
int GetMultiFileNext( char* pfilepath ) ;
int GetTheFileFirst( char* ppath , char* pfilepath ) ;
int GetTheFileNext( char* pfilepath ) ;
void FileLastSx( ) ;
int GetStrLen( char* sbuf , int scount ) ;
BYTE* GetUserBuf( int buflen ) ;
CString GetFileNamePart( CString& path ) ;
CString ExcludeFileNamePart( CString& path ) ;
int ListUpAllSubDir( char* ppath , char*bufp , int bufsize ) ;
static char* GetNextPointerForSubDir( char* cp , int ccount ) ;
void SeparatePath( CString& path , CString& purepath , CString& filename ) ;
int MultiPathToEachPath( const char* sbuf , CString* pstr , int pstrcount ) ;
int GetStringParam( const char* sbuf , CString* pstr , int pstrcount ) ;
CString GetStringTopParam( BYTE* sbuf , int slen , int* pcheckedlen ) ;
int GetLastYenPos( BYTE* buf , int blen ) ;
int GetErrorCode( ) ;
int ListUpSubDir( char* ppath , char*bufp , int bufsize , int bFullForm=TRUE ) ;
int GetTheSubDirFirst( char* ppath , char* psubdirpath , int bFullForm=TRUE ) ;
int GetTheSubDirNext( char* psubdirpath , int bFullForm=TRUE ) ;
void GetTheSubDirLast( ) ;

static const char szDirFileTooMany[] = "ディレクトリ、またはファイルの個数が多すぎて処理できません。" ;
static const char szMemoryInsufficient[] = "メモリ不足です。" ;

static CString multipath[MAXMULTIPATHCOUNT] ;
static int multipathcount ;
static int nextmultipathindex ;
static char ppathsave[_MAX_PATH+1] ;

static WIN32_FIND_DATA ffindt ;
static HANDLE hffind ;

//*****************************************************************************
// 機能 :指定のディレクトリ下の指定ファイルを全てリストアップする(サブディレクトリも対象)。
//  入力 :  ppath = 絶対パス名("x:\xxx\xxx\filename"形式)(例)"x:\xxx\xxx\*.*"
//            bufp = ファイルの絶対パス名を格納する領域へのポインタ
//            bufsize = bufpのサイズ
//  戻り値: 指定ファイルの個数、-1の時はバッファオーバー。
//  注意 : bufpへの格納形式は次の通り。
//            x:\xxx\xxx\realfilename(NULL)
//              ----------------
//*****************************************************************************
int ListUpAllFiles( char* ppath , char* bufp , int bufsize )
{
    int index = 0 ;

    int fcount = ListUpFiles( ppath , &bufp[index] , bufsize-index ) ;  // 最初の段をリストアップ
    if ( fcount == -1 )
    {
        AfxMessageBox( szDirFileTooMany ) ;
        return -1 ;

    }

    index = GetStrLen( &bufp[index] , fcount ) ;


    BYTE* wbuf = GetUserBuf( DIRFUNCTIONBUFLEN+10 ) ;   // 注意:wbufの削除を忘れないこと!!!
    if ( wbuf == NULL )
        return fcount ;

    CString dirpath = (const char*)ppath ;              // "x:\xxx\xxx\filename"形式
    CString filename = GetFileNamePart( dirpath ) ;     // "filename"形式
    CString realpath = ExcludeFileNamePart( dirpath ) ; // "x:\xxx\xxx\"形式
    realpath += "*.*" ;                                 // "x:\xxx\xxx\*.*"形式

    int dircount = ListUpAllSubDir( (char*)(const char*)realpath , (char*)wbuf , DIRFUNCTIONBUFLEN ) ;
    if ( dircount == -1 )
    {
        delete wbuf ;
        AfxMessageBox( szDirFileTooMany ) ;
        return fcount ;

    }
    
    int i ;
    int k ;
    int len = 0 ;                   // 念のため0設定
    for ( i = 0 , k = 0 ; i < dircount ; i++ , k += (len + 1) )
    {
        len = (int)strlen( (const char*)&wbuf[k] ) ;
        CString filepath = (const char*)&wbuf[k] ;      // "x:\xxx\xxx\" 形式
        filepath += filename ;                          // "x:\xxx\xxx\filename" 形式

        int eachcount = ListUpFiles( (char*)(const char*)filepath , &bufp[index] , bufsize-index ) ;    // 各段をリストアップ
        if ( eachcount == -1 )
            break ;

        fcount += eachcount ;
        
        int thislen = GetStrLen( &bufp[index] , eachcount ) ;
        index += thislen ;
        if ( bufsize-index < _MAX_PATH+1 )
            break ;

    }

    delete wbuf ;

    if ( i < dircount )
        AfxMessageBox( szDirFileTooMany ) ;

    return fcount ;

}
    

//*****************************************************************************
// 機能 : 指定のパス下の指定ファイルを全てリストアップする(ただし1段のみ)。
//  入力 :  ppath = 絶対パス名("x:\xxx\xxx\filename"形式)(例)"x:\xxx\xxx\*.wbr"
//            bufp = サブディレクトリの絶対パス名を格納する領域へのポインタ
//            bufsize = bufpのサイズ
//  戻り値: 指定ファイルの個数、-1の時はバッファオーバー。
//  注意 : bufpへの格納形式は次の通り。
//            x:\xxx\xxx\realfilename(NULL)
//              ----------------
//*****************************************************************************
int ListUpFiles( char* ppath , char* bufp , int bufsize )
{
    int i ;
    int count ;
    int len ;

    if ( GetMultiFileFirst( ppath , bufp ) != 0 )
        return 0 ;

    for ( i = 0 , count = 0 ; ; )
    {
        len = (int)strlen( (const char*)&bufp[i] ) ;
        i += len+1 ;
        count++ ;
        
        if ( i >= bufsize-(_MAX_PATH+1) )
        {
            FileLastSx( ) ;
            break ;
        }

        if ( GetMultiFileNext( &bufp[i] ) != 0)
            break ;

    }

    if ( i >= bufsize-(_MAX_PATH+1) )
        return -1 ;
    else
        return count ;

}


//*****************************************************************************
// 機能 : 指定のファイル名に一致する最初のファイルを見つけて戻す。
//  入力 : ppath = マルチ絶対パス("x:\xxx\xxx\filename filename1 filename2, ..."形式であること。filenameはワイルドカード可)
//            pfilepath = (見つかればここに、"x:\xxx\xxx\fff"形式で戻る)
//  戻り値: 0:OK , 1:ない
//  注意  :  エラー発生時は、1で戻る。
//*****************************************************************************
int GetMultiFileFirst( char* ppath , char* pfilepath )
{

    multipathcount = MultiPathToEachPath( (const char*)ppath , multipath , MAXMULTIPATHCOUNT ) ;
    if ( multipathcount == 0 )
    {
        ASSERT( FALSE ) ;
        return 1 ;

    }

    nextmultipathindex = 0 ;

    int i ;
    for ( i = nextmultipathindex ; i < multipathcount ; i++ )
    {
    
        if ( GetTheFileFirst( (char*)(const char*)multipath[i] , pfilepath ) == 0 )
            break ;

    }

    nextmultipathindex = i ;

    if ( i == multipathcount )
        return 1 ;
    else
        return 0 ;

}



//*****************************************************************************
// 機能 : 指定のファイル名に一致する次のファイルを見つけて戻す。
//  入力 :  pfilepath = (見つかればここに、"x:\xxx\xxx\fff"形式で戻る)
//  戻り値: 0:OK , 1:ない
//  注意 : GetTheFileFirstを事前に呼び、成功していること。
//  注意  :  エラー発生時は、1で戻る。
//*****************************************************************************
int GetMultiFileNext( char* pfilepath )
{

    if ( GetTheFileNext( pfilepath ) == 0 )
        return 0 ;

    if ( nextmultipathindex == multipathcount-1 )
        return 1 ;

    nextmultipathindex++ ;

    int i ;
    for ( i = nextmultipathindex ; i < multipathcount ; i++ )
    {
    
        if ( GetTheFileFirst( (char*)(const char*)multipath[i] , pfilepath ) == 0 )
            break ;

    }

    nextmultipathindex = i ;

    if ( i == multipathcount )
        return 1 ;
    else
        return 0 ;

}

    
//*****************************************************************************
// 機能 : hffindの解放
//*****************************************************************************
void FileLastSx( )
{
    FindClose( hffind ) ;
}


//*****************************************************************************
// 機能 : 指定のファイル名に一致する最初のファイルを見つけて戻す。
//  入力 : ppath = 絶対パス("x:\xxx\xxx\filename"形式であること。filenameはワイルドカード可)
//            pfilepath = (見つかればここに、"x:\xxx\xxx\fff"形式で戻る)
//  戻り値: 0:OK , 1:ない , 2:エラー発生
//*****************************************************************************
int GetTheFileFirst( char* ppath , char* pfilepath )
{
    int i ;

    int len = (int)strlen( (const char*)ppath ) ;

    i = GetLastYenPos( (BYTE*)ppath , len ) ;

    ASSERT( i > 0 ) ;
    strncpy( ppathsave , (const char*)&ppath[0] , i+1 ) ;
    ppathsave[i+1] = 0 ;

    hffind = FindFirstFile( ppath , &ffindt ) ;

    if ( hffind == INVALID_HANDLE_VALUE )
        return GetErrorCode( ) ;

    for ( ; ; )
    {

        if ( !(ffindt.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_SYSTEM)) )
            break ;

        if ( !FindNextFile( hffind , &ffindt ) )
        {
            FileLastSx( ) ;
            return GetErrorCode( ) ;
        }
    }


    strcpy( pfilepath , ppathsave ) ;
    strcat( pfilepath , ffindt.cFileName ) ;
    return 0 ;
}


//*****************************************************************************
// 機能 : 指定のファイル名に一致する次のファイルを見つけて戻す。
//  入力 :  pfilepath = (見つかればここに、"x:\xxx\xxx\fff"形式で戻る)
//  戻り値: 0:OK , 1:ない , 2:エラー発生
//  注意 : GetTheFileFirstを事前に呼び、成功していること。
//*****************************************************************************
int GetTheFileNext( char* pfilepath )
{

    if ( !FindNextFile( hffind , &ffindt ) )
    {
        FileLastSx( ) ;
        return GetErrorCode( ) ;

    }

    for ( ; ; )
    {

        if ( !(ffindt.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_SYSTEM)) )
            break ;
    
        if ( !FindNextFile( hffind , &ffindt ) )
        {
            FileLastSx( ) ;
            return GetErrorCode( ) ;
        }
    }

    strcpy( pfilepath , ppathsave ) ;
    strcat( pfilepath , ffindt.cFileName ) ;
    return 0 ;
}


//*****************************************************************************
// 機能 :指定バッファ内で指定個数の文字列の合わせた長さを戻す。
//  注意 :bufpへの格納形式は次の通り。各文字列最後の(NULL)も含めたサイズを戻す。
//          x:\xxx\xxx\realfilename(NULL)
//              ----------------
//*****************************************************************************
int GetStrLen( char* sbuf , int scount )
{
    int k ;
    int i ;
    int len ;
    for ( i = 0 , k = 0 ; i < scount ; i++ , k += (len + 1) )
        len = (int)strlen( (const char*)&sbuf[k] ) ;

    return k ;

}

//*****************************************************************************
//  機能  :指定サイズのバッファを確保して戻す。
//  戻り値:NULLの時は、確保できなかったことを意味する。
//  注意  :バッファの解放は呼ぶ側で行なうこと。
//*****************************************************************************
BYTE* GetUserBuf( int buflen )
{

    BYTE* wbuf ;

    TRY
    {
        wbuf = new BYTE[buflen] ;
    }
    CATCH( CMemoryException , e )
    {
        AfxMessageBox( szMemoryInsufficient ) ;
        return NULL ;

    }
    END_CATCH

    return wbuf ;

}

//*****************************************************************************
//  機能  :指定のパスからファイル名の部分を取り出して戻す。
//*****************************************************************************
CString GetFileNamePart( CString& path )
{

    char fname[_MAX_FNAME+1];
    char ext[_MAX_EXT+1] ;
    _splitpath( (const char*)path, NULL, NULL, fname, ext ) ;

    CString tstr = fname ;
    tstr += ext ;

    return tstr ;

}


//*****************************************************************************
//  機能  :指定のパスからファイル名(fff.xxx)の部分を除いたものを戻す。
//*****************************************************************************
CString ExcludeFileNamePart( CString& path )
{

    char path_buffer[_MAX_PATH+1];
    char drive[_MAX_DRIVE+1];
    char dir[_MAX_DIR+1];
    char fname[_MAX_FNAME+1];
    char ext[_MAX_EXT+1];

    _splitpath( (const char*)path, drive, dir, fname, ext ) ;
    _makepath( path_buffer, drive, dir, NULL, NULL );

    CString tstr = (const char*)path_buffer ;

    return tstr ;

}


//*****************************************************************************
// 機能 : 指定のパス下のサブディレクトリをそのネストも含めて全てリストアップする(全段対応)。
//  入力 :  ppath = 絶対パス名("x:\xxx\xxx\*.*"形式)
//            bufp = サブディレクトリの絶対パス名を格納する領域へのポインタ
//            bufsize = bufpのサイズ(INT_MAX以下であること)
//  戻り値: サブディレクトリの個数、-1の時はバッファオーバー。
//  注意 : bufpへの格納形式は次の通り。
//              x:\xxx\xxx\(NULL)  : データの最後は\で次がNULL
//              ----------------
//*****************************************************************************
int ListUpAllSubDir( char* ppath , char*bufp , int bufsize )
{

    int i ;
    int count ;
    int len ;
    char* nextbufp ;
    char* nextnamep ;
    int restsize ;
    int tcount ;
    char namepath[_MAX_PATH+1] ;

    ASSERT( bufsize <= INT_MAX && bufsize >= _MAX_PATH+1 ) ;

    count = ListUpSubDir( ppath , bufp , bufsize ) ;
    if ( count == -1 || count == 0 )
        return count ;

    nextbufp = GetNextPointerForSubDir( bufp , count ) ;
    restsize = bufsize - (int)(nextbufp-bufp) ;
    tcount = count ;
    nextnamep = bufp ;

    for ( i = 0 ; i < tcount ; i++ )
    {
        len = (int)strlen( (const char*)nextnamep ) ;
        strcpy( namepath , (const char*)nextnamep ) ;
        strcat( namepath , "*.*" ) ;
        nextnamep += len ;
        nextnamep++ ;               // NULLの分

        count = ListUpSubDir( namepath , nextbufp , restsize ) ;
        if ( count == -1 )
            return -1 ;                 //<-----------------------エラー処理!!!!!
        if ( count > 0 )
        {       
            nextbufp = GetNextPointerForSubDir( nextbufp , count ) ;
            restsize = bufsize - (int)(nextbufp-bufp) ;
            tcount += count ;
        }
    }
    return tcount ;
}


//*****************************************************************************
// 機能 : 指定の現在の位置と個数から次にサブディレクトリを格納すべき位置を求める。
//*****************************************************************************
static char* GetNextPointerForSubDir( char* cp , int ccount )
{
    int i ;

    char* nextp = cp ;
    for ( i = 0 ; i < ccount ; i++ )
    {
        nextp = strchr( (const char*)nextp , '\0' ) ;
        ASSERT( nextp != NULL ) ;
        nextp++ ;
    }
    return nextp ;
}
        

//***************************************************************************
//  機能 :指定のフルパス文字列からファイル名をその前までの部分に分解して戻す。
//  注意  :(例)
//              c:\wk\xxx.txt ----> c:\wk\     <------最後に\が付く!
//                                  xxx.txt
//***************************************************************************
void SeparatePath( CString& path , CString& purepath , CString& filename )
{
    purepath = "" ;
    filename = "" ;

    int plen = path.GetLength( ) ;
    if ( plen == 0 )
        return ;

    int pos = path.ReverseFind( '\\' ) ;
    if ( pos == -1 )
    {
        ASSERT( FALSE ) ;
        return ;

    }

    if ( pos == plen-1 )
    {
        purepath = path ;
        filename = "" ;
        return ;

    }

    purepath = path.Left( pos+1 ) ;     // \ を含めて取り出し
    filename = path.Right( plen-(pos+1) ) ;

}


//***************************************************************************
//  機能 :指定のマルチパス指定を解析し、フルパス配列にして戻す。
//  入力  :pstrcount = pstr[]の配列要素数
//  戻り値:取り出したフルパス配列の要素数
//  注意  :囲み記号ははずした形で戻す。
//          マルチパス指定は次のような形式とする。
//              フルパス指定 ファイル2 ファイル3, ----
//                  (注)ファイル2, ファイル3,..の前には \ マークはないこと!
//              フルパス指定 フルパス指定,.... 
//              (先頭は必ずフルパス指定、その後はファイル名のみまたはフルパス)
//          (例)
//              
//          c:\wk\*.c                   ---> c:\wk\*.c
//          c:\wk\*.c *.h               ---> c:\wk\*.c
//                                           *.h
//          "c:\wk\*.c *.h"             ---> c:\wk\*.c *.h
//          "c:\wk\*.c ""*.h"           ---> c:\wk\*.c "*.h    ---連続する"は単なる"と見なす
//***************************************************************************
int MultiPathToEachPath( const char* sbuf , CString* pstr , int pstrcount )
{
    int elementcount = GetStringParam( sbuf , pstr , pstrcount ) ;
    if ( elementcount == 0 )
        return 0 ;

    if ( elementcount == 1 )
        return 1 ;                  // FullPath指定のみ!


    CString purepath ;
    CString filename ;
    SeparatePath( pstr[0] , purepath , filename ) ;

    int i ;
    for ( i = 1 ; i < elementcount ; i++ )
    {
        CString wkstr = purepath ;
        CString wkfilename = pstr[i] ;
        int wkfilenamelen = wkfilename.GetLength( ) ;
        if ( wkfilenamelen > 2 && wkfilename[1] == ':' )
            NULL ;                      // 元々フルパスと解釈!!!
        else
        {

            if ( wkfilenamelen > 0 && wkfilename[0] == '\\' )
            {
                ASSERT( FALSE ) ;

                CString wkfilename2 = wkfilename.Right( wkfilenamelen-1 ) ;
                wkfilename = wkfilename2 ;

            }

            wkstr += wkfilename ;                   // c:\wk\ + xxxx.txt ----> c:\wk\xxxx.txt
            pstr[i] = wkstr ;

        }

    }

    return elementcount ;

}


//***************************************************************************
//  機能 :指定バッファの文字列を半角SPを区切りとした文字列に分解して戻す。
//          ""で囲まれている場合は、空白自体が文字列と見なされる。
//          ""で囲まれていない場合は、末尾の空白は無視
//  入力  :pstrcount = pstr[]の配列要素数
//  戻り値:取り出した文字列の個数
//  注意  :c:\wk\*.c                   ---> c:\wk\*.c
//          c:\wk\*.c *.h               ---> c:\wk\*.c
//                                           *.h
//          "c:\wk\*.c *.h"             ---> c:\wk\*.c *.h
//          "c:\wk\*.c ""*.h"           ---> c:\wk\*.c "*.h    ---連続する"は単なる"と見なす
//          MAXPARAMLENを越えるパラメータはMAXPARAMLEN+1以降が無視される
//***************************************************************************
int GetStringParam( const char* sbuf , CString* pstr , int pstrcount )
{
    int slen = (int)strlen( sbuf ) ;
    if ( slen == 0 )
        return 0 ;

    int i ;
    int k ;
    for ( i = 0 , k = 0 ; i < slen && k < pstrcount ; )
    {

        int checkedlen ;
        int restlen = slen - i ;
        CString estr = GetStringTopParam( (BYTE*)(&sbuf[i]) , restlen , &checkedlen ) ;
        if ( estr.IsEmpty( ) )
            break ;

        pstr[k] = estr ;
        k++ ;

        i += checkedlen ;
        for ( ; i < slen ; i++ )
        {
            if ( sbuf[i] != C_SPACE )
                break ;

        }

    }

    return k ;

}



//***************************************************************************
//  機能 :指定バッファから先頭の文字列を取り出して戻す。
//          半角SPを区切りとする。
//          ""で囲まれている場合は、空白自体が文字列と見なされる。
//  戻り値:取り出した文字列
//  注意  :c:\wk\*.c                   ---> c:\wk\*.c
//          c:\wk\*.c *.h               ---> c:\wk\*.c
//                                           *.h
//          "c:\wk\*.c *.h"             ---> c:\wk\*.c *.h
//          "c:\wk\*.c ""*.h"           ---> c:\wk\*.c "*.h    ---連続する"は単なる"と見なす
//          MAXPARAMLENを越える場合は、Emptyで戻る。
//          *pcheckedlenは取り出した文字列長より大の場合あり(途中に"xx"がある場合)
//***************************************************************************
CString GetStringTopParam( BYTE* sbuf , int slen , int* pcheckedlen )
{
    CString estr = "" ; 
    BYTE ebuf[MAXPARAMLEN+1] ;

    *pcheckedlen = 0 ;

    if ( slen == 0 )
        return estr ;

    int i ;
    int k ;
    int bSpaceOK = FALSE ;
    for ( i = 0 , k = 0 ; i < slen && k < MAXPARAMLEN ; i++ )
    {
        BYTE bt = sbuf[i] ;     
        
        if ( bt == C_SPACE )
        {
            if ( !bSpaceOK )
                break ;
            
            ebuf[k] = bt ;
            k++ ;
            continue ;

        }

        if ( bt == C_QUOT )
        {
            if ( i+1 < slen && sbuf[i+1] == C_QUOT )
            {               // 単なる文字と見なす!!!
                ebuf[k] = bt ;
                k++ ;
                i++ ;       // for 連続するC_QUOTをスキップ
                continue ;

            }

            if ( !bSpaceOK )
                bSpaceOK = TRUE ;
            else
                bSpaceOK = FALSE ;

            continue ;

        }

        ebuf[k] = bt ;
        k++ ;

    }

    *pcheckedlen = i ;

    if ( k == MAXPARAMLEN )
        return estr ;           // パラメータが長すぎる場合は、emptyで戻す!
    
    ebuf[k] = 0 ;               // set NULL 

    estr = (const char*)ebuf ;

    return estr ;

}

//*****************************************************************************
// 機能 :指定のパスをチェックして、最後についている\の位置を戻す。
//  注意  :\がない場合には、 -1 が戻る!!!
//*****************************************************************************
int GetLastYenPos( BYTE* buf , int blen )
{
    int pos = -1 ;          // 初期値!!!

    int i ;
    for ( i = 0 ; i < blen ; i++ )
    {
        if ( _ismbblead( buf[i] ) )
        {
            i++ ;
            continue ;

        }

        if ( buf[i] == '\\' )
            pos = i ;

    }

    return pos ;

}


//*****************************************************************************
// 機能 :単に 1 で戻すだけ
//  注意 :for debug
//*****************************************************************************
int GetErrorCode( )
{
    DWORD errord = GetLastError( ) ;
    return 1 ;

}


//*****************************************************************************
// 機能 : 指定のパス下のサブディレクトリを全てリストアップする(ただし1段のみ)。
//  入力 :  ppath = 絶対パス名("x:\xxx\xxx\*.*"形式)
//            bufp = サブディレクトリの絶対パス名を格納する領域へのポインタ
//            bufsize = bufpのサイズ(INT_MAX以下であること)
//  戻り値: サブディレクトリの個数、-1の時はバッファオーバー。
//  注意 : bufpへの格納形式は次の通り。
//              x:\xxx\xxx\(NULL)  : データの最後は\で次がNULL
//              ----------------
//*****************************************************************************
int ListUpSubDir( char* ppath , char*bufp , int bufsize , int bFullForm )
{
    int i ;
    int count ;
    int len ;

    ASSERT( bufsize <= INT_MAX && bufsize >= _MAX_PATH+1 ) ;

    if ( GetTheSubDirFirst( ppath , bufp , bFullForm ) != 0 )
        return 0 ;


    for ( i = 0 , count = 0 ; ; )
    {
        len = (int)strlen( (const char*)&bufp[i] ) ;
        if ( len >= 3 && bufp[len-2] == '.' && bufp[len-3] == '\\' )
        {
            NULL ;              // 自分自身は除く
        }
        else if ( len >= 4 && bufp[len-2] == '.' && bufp[len-3] == '.' && bufp[len-4] == '\\' )
        {
            NULL ;              // 自分の親の除く
        }
        else
        {
            i += len+1 ;
            count++ ;
        }
        
        if ( i >= bufsize-(_MAX_PATH+1) )
        {
            GetTheSubDirLast( ) ;
            break ;
        }
        if ( GetTheSubDirNext( &bufp[i] , bFullForm ) != 0)
            break ;
    }

    if ( i >= bufsize-(_MAX_PATH+1) )
        return -1 ;
    else
        return count ;
}


//*****************************************************************************
// 機能 : 指定のパスの最初のサブディレクトリを見つけて戻す。
//  入力 : ppath = 絶対パス("x:\xxx\xxx\*.*"形式であること)
//            psubdirpath = (見つかればここに、"x:\xxx\xxx\yyy\"形式で戻る) --- bFullFormがTRUEの時
//            psubdirpath = (見つかればここに、"yyy"形式で戻る) --- bFullFormがFALSEの時
//  戻り値: 0:OK , 1:ない , 2:エラー発生
//*****************************************************************************
int GetTheSubDirFirst( char* ppath , char* psubdirpath , int bFullForm )
{
    int len = (int)strlen( (const char*)ppath ) ;

    ASSERT( len > 3 && strcmp( (const char*)&ppath[len-3] , "*.*" ) == 0 ) ;

    strcpy( ppathsave , (const char*)ppath ) ;

    hffind = FindFirstFile( ppathsave , &ffindt ) ;

    if ( hffind == INVALID_HANDLE_VALUE )
        return GetErrorCode( ) ;

    for ( ; ; )
    {
        if ( ffindt.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
            break ;

        if ( !FindNextFile( hffind , &ffindt ) )
        {
            FindClose( hffind ) ;
            return GetErrorCode( ) ;
        }

    }

    if ( bFullForm )
    {
        strncpy( psubdirpath , ppath , len-3 ) ;
        strcpy( &psubdirpath[len-3] , ffindt.cFileName ) ;
        len = (int)strlen( psubdirpath ) ;
        psubdirpath[len] = '\\' ;
        psubdirpath[len+1] = 0 ;
    }
    else
        strcpy( psubdirpath , ffindt.cFileName ) ;

    return 0 ;
}

                
//*****************************************************************************
// 機能 : 指定のパスの次のサブディレクトリを見つけて戻す。
//  入力 : psubdirpath = (見つかればここに、"x:\xxx\xxx\yyy\"形式で戻る) --- bFullFormがTRUEの時
//            psubdirpath = (見つかればここに、"yyy"形式で戻る) --- bFullFormがFALSEの時
//  戻り値: 0:OK , 1:ない , 2:エラー発生
//  注意 : GetTheSubDirFirstを事前に呼び、成功していること。
//*****************************************************************************
int GetTheSubDirNext( char* psubdirpath , int bFullForm )
{
    int len = (int)strlen( (const char*)ppathsave ) ;

    if ( !FindNextFile( hffind , &ffindt ) )
    {
        FindClose( hffind ) ;
        return GetErrorCode( ) ;
    }

    for ( ; ; )
    {
        if ( ffindt.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
            break ;

        if ( !FindNextFile( hffind , &ffindt ) )
        {
            FindClose( hffind ) ;
            return GetErrorCode( ) ;
        }

    }

    if ( bFullForm )
    {
    
        strncpy( psubdirpath , ppathsave , len-3 ) ;
        strcpy( &psubdirpath[len-3] , ffindt.cFileName ) ;
        len = (int)strlen( psubdirpath ) ;
        psubdirpath[len] = '\\' ;
        psubdirpath[len+1] = 0 ;

    }
    else
        strcpy( psubdirpath , ffindt.cFileName ) ;

    return 0 ;
}
        


//*****************************************************************************
// 機能 : hffindの解放
//*****************************************************************************
void GetTheSubDirLast( )
{
    FindClose( hffind ) ;
}


//*****************************************************************************
// ListUpAllFiles.cpp : Ver1.00  2006/12/26
// Example : int count = ListUpAllFiles( "d:\\wk\\wk_temp\\*.* d:\\wka\\*.txt" , pc , 1024*500 ) ;
//
// Copyright(C) Edcom Inc. (http://www.edcom.jp/) All rights reserved. 
//*****************************************************************************