Code Search for Developers
 
 
  

SFileFindFile.cpp from MaNGOS at Krugle


Show SFileFindFile.cpp syntax highlighted

/*****************************************************************************/
/* SFileFindFile.cpp                      Copyright (c) Ladislav Zezula 2003 */
/*---------------------------------------------------------------------------*/
/* A module for file searching within MPQs                                   */
/*---------------------------------------------------------------------------*/
/*   Date    Ver   Who  Comment                                              */
/* --------  ----  ---  -------                                              */
/* 25.03.03  1.00  Lad  The first version of SFileFindFile.cpp               */
/*****************************************************************************/

#define __STORMLIB_SELF__
#include "StormLib.h"
#include "SCommon.h"

//-----------------------------------------------------------------------------
// Defines

#define LISTFILE_CACHE_SIZE 0x1000

//-----------------------------------------------------------------------------
// Local functions

static BOOL IsValidSearchHandle(TMPQSearch * hs)
{
    if(hs == NULL || IsBadReadPtr(hs, sizeof(TMPQSearch)))
        return FALSE;

    if(!IsValidMpqHandle(hs->ha))
        return FALSE;

    return TRUE;
}

// This function compares a string with a wildcard search string.
// returns TRUE, when the string matches with the wildcard.
BOOL CheckWildCard(const char * szString, const char * szWildCard)
{
    char * szTemp;                      // Temporary helper pointer
    int nResult = 0;                    // For memcmp return values
    int nMustNotMatch = 0;              // Number of following chars int szString,
                                        // which must not match with szWildCard
    int nMustMatch = 0;                 // Number of the following characters,
                                        // which must match

    // When the string is empty, it does not match with every wildcard
    if(*szString == 0)
        return FALSE;

    // When the mask is empty, it matches to every wildcard
    if(szWildCard == NULL || *szWildCard == 0)
        return FALSE;

    // Do normal test
    for(;;)
    {
        switch(*szWildCard)
        {
            case '*': // Means "every number of characters"
                // Skip all asterisks
                while(*szWildCard == '*')
                    szWildCard++;

                // When no more characters in wildcard, it means that the strings match
                if(*szWildCard == 0)
                    return TRUE;

                // The next N characters must not agree
                nMustNotMatch |= 0x70000000;
                break;
            
            case '?':  // Means "One or no character"
                while(*szWildCard == '?')
                {
                    nMustNotMatch++;
                    szWildCard++;
                }
                break;

            default:
                // If the two characters match
                if(toupper(*szString) == toupper(*szWildCard))
                {
                    // When end of string, they agree
                    if(*szString == 0)
                        return TRUE;

                    nMustNotMatch = 0;
                    szWildCard++;
                    szString++;
                    break;
                }

                // If the next character must match, the string does not match
                if(nMustNotMatch == 0)
                    return FALSE;

                // Count the characters which must match after characters
                // that must not match
                szTemp = (char *)szWildCard;
                nMustMatch = 0;
                while(*szTemp != 0 && *szTemp != '*' && *szTemp != '?')
                {
                    nMustMatch++;
                    szTemp++;
                }

                // Now skip characters from szString up to number of chars
                // that must not match
                nResult = -1;
                while(nMustNotMatch > 0 && *szString != 0)
                {
                    if((nResult = _strnicmp(szString, szWildCard, nMustMatch)) == 0)
                        break;
                    
                    szString++;
                    nMustNotMatch--;
                }

                // Make one more comparison
                if(nMustNotMatch == 0)
                    nResult = _strnicmp(szString, szWildCard, nMustMatch);

                // If a match has been found, continue the search
                if(nResult == 0)
                {
                    nMustNotMatch = 0;
                    szWildCard += nMustMatch;
                    szString   += nMustMatch;
                    break;
                }
                return FALSE;
        }
    }
}

// Performs one MPQ search
// TODO: Test for archives > 4GB
static int DoMPQSearch(TMPQSearch * hs, SFILE_FIND_DATA * lpFindFileData)
{
    TMPQArchive * ha = hs->ha;
    TFileNode * pNode;
    TMPQHash * pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize;
    TMPQHash * pHash = ha->pHashTable + hs->dwNextIndex;

    // Do until some file found or no more files
    while(pHash < pHashEnd)
    {
        pNode = ha->pListFile[hs->dwNextIndex++];

        // If this entry is free, do nothing
        if(pHash->dwBlockIndex < HASH_ENTRY_FREE && (DWORD_PTR)pNode < HASH_ENTRY_FREE)
        {
            // Check the file name.
            if(CheckWildCard(pNode->szFileName, hs->szSearchMask))
            {
                TMPQBlock * pBlock = ha->pBlockTable + pHash->dwBlockIndex;

                lpFindFileData->lcLocale     = pHash->lcLocale;
                lpFindFileData->dwFileSize   = pBlock->dwFSize;
                lpFindFileData->dwFileFlags  = pBlock->dwFlags;
                lpFindFileData->dwBlockIndex = pHash->dwBlockIndex;
                lpFindFileData->dwCompSize   = pBlock->dwCSize;

                // Fill the file name and plain file name
                strcpy(lpFindFileData->cFileName, pNode->szFileName);
                lpFindFileData->szPlainName = strrchr(lpFindFileData->cFileName, '\\');
                if(lpFindFileData->szPlainName == NULL)
                    lpFindFileData->szPlainName = lpFindFileData->cFileName;
                else
                    lpFindFileData->szPlainName++;

                // Fill the next entry
                return ERROR_SUCCESS;
            }
        }

        pHash++;
    }

    // No more files found, return error
    return ERROR_NO_MORE_FILES;
}

// TODO: Test for archives > 4GB
static void FreeMPQSearch(TMPQSearch *& hs)
{
    if(hs != NULL)
    {
        FREEMEM(hs);
        hs = NULL;
    }
}

//-----------------------------------------------------------------------------
// Public functions

// TODO: Test for archives > 4GB
HANDLE WINAPI SFileFindFirstFile(HANDLE hMPQ, const char * szMask, SFILE_FIND_DATA * lpFindFileData, const char * szListFile)
{
    TMPQArchive * ha = (TMPQArchive *)hMPQ;
    TMPQSearch * hs = NULL;             // Search object handle
    size_t nSize  = 0;
    int nError = ERROR_SUCCESS;

    // Check for the valid parameters
    if(nError == ERROR_SUCCESS)
    {
        if(!IsValidMpqHandle(ha))
            nError = ERROR_INVALID_PARAMETER;
       
        if(szMask == NULL || lpFindFileData == NULL)
            nError = ERROR_INVALID_PARAMETER;

        if(szListFile == NULL && !IsValidMpqHandle(ha))
            nError = ERROR_INVALID_PARAMETER;
    }

    // Include the listfile into the MPQ's internal listfile
    // Note that if the listfile name is NULL, do nothing because the
    // internal listfile is always included.
    if(nError == ERROR_SUCCESS && szListFile != NULL)
        nError = SFileAddListFile((HANDLE)ha, szListFile);

    // Allocate the structure for MPQ search
    if(nError == ERROR_SUCCESS)
    {
        nSize = sizeof(TMPQSearch) + strlen(szMask) + 1;
        if((hs = (TMPQSearch *)ALLOCMEM(char, nSize)) == NULL)
            nError = ERROR_NOT_ENOUGH_MEMORY;
    }

    // Perform the first search
    if(nError == ERROR_SUCCESS)
    {
        memset(hs, 0, sizeof(TMPQSearch));
        hs->ha          = ha;
        hs->dwNextIndex = 0;
        strcpy(hs->szSearchMask, szMask);
        nError = DoMPQSearch(hs, lpFindFileData);
    }

    // Cleanup
    if(nError != ERROR_SUCCESS)
    {
        FreeMPQSearch(hs);
        SetLastError(nError);
    }
    
    // Return the result value
    return (HANDLE)hs;
}

// TODO: Test for archives > 4GB
BOOL WINAPI SFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData)
{
    TMPQSearch * hs = (TMPQSearch *)hFind;
    int nError = ERROR_SUCCESS;

    // Check the parameters
    if(nError == ERROR_SUCCESS)
    {
        if(!IsValidSearchHandle(hs) || lpFindFileData == NULL)
            nError = ERROR_INVALID_PARAMETER;
    }

    if(nError == ERROR_SUCCESS)
        nError = DoMPQSearch(hs, lpFindFileData);

    if(nError != ERROR_SUCCESS)
    {
        SetLastError(nError);
        return FALSE;
    }
    return TRUE;
}

// TODO: Test for archives > 4GB
BOOL WINAPI SFileFindClose(HANDLE hFind)
{
    TMPQSearch * hs = (TMPQSearch *)hFind;

    // Check the parameters
    if(!IsValidSearchHandle(hs))
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    FreeMPQSearch(hs);
    return TRUE;
}




See more files for this project here

MaNGOS

MaNGOS is an object-oriented Massively Multiplayer Online Role-Playing Game Server (MMORPGS). It\'s an educational project, to help developers get familar with large scale C++ and C# development projects.

Project homepage: http://sourceforge.net/projects/mangos
Programming language(s): C,C++,SQL
License: gpl2

  bzip2/
    CHANGES
    LICENSE
    Makefile
    Makefile-libbz2_so
    README
    README.COMPILATION.PROBLEMS
    README.XML.STUFF
    Y2K_INFO
    blocksort.c
    bz-common.xsl
    bz-fo.xsl
    bz-html.xsl
    bzdiff
    bzdiff.1
    bzgrep
    bzgrep.1
    bzip.css
    bzip2.1
    bzip2.1.preformatted
    bzip2.c
    bzip2.txt
    bzip2recover.c
    bzlib.c
    bzlib.h
    bzlib_private.h
    bzmore
    bzmore.1
    compress.c
    crctable.c
    decompress.c
    dlltest.c
    dlltest.dsp
    entities.xml
    format.pl
    huffman.c
    libbz2.def
    libbz2.dsp
    makefile.msc
    manual.html
    manual.pdf
    manual.ps
    manual.xml
    mk251.c
    randtable.c
    sample1.bz2
    sample1.ref
    sample2.bz2
    sample2.ref
    sample3.bz2
    sample3.ref
    spewG.c
    unzcrash.c
    words0
    words1
    words2
    words3
    xmlproc.sh
  huffman/
    huff.cpp
    huff.h
  pklib/
    crc32.c
    crc32_pk.c
    explode.c
    implode.c
    pklib.h
  wave/
    wave.cpp
    wave.h
  zlib/
    amiga/
    contrib/
    msdos/
    nt/
    os2/
    ChangeLog
    FAQ
    INDEX
    Makefile
    Makefile.in
    Makefile.riscos
    README
    adler32.c
    algorithm.txt
    compress.c
    configure
    crc32.c
    deflate.c
    deflate.h
    descrip.mms
    example.c
    gzio.c
    infblock.c
    infblock.h
    infcodes.c
    infcodes.h
    inffast.c
    inffast.h
    inffixed.h
    inflate.c
    inftrees.c
    inftrees.h
    infutil.c
    infutil.h
    maketree.c
    minigzip.c
    trees.c
    trees.h
    uncompr.c
    zconf.h
    zlib.3
    zlib.h
    zlib.html
    zmemory.c
    zutil.c
    zutil.h
  GfxDecode.cpp
  Makefile
  SCommon.cpp
  SCommon.h
  SCompression.cpp
  SFileCompactArchive.cpp
  SFileCreateArchiveEx.cpp
  SFileExtractFile.cpp
  SFileFindFile.cpp
  SFileOpenArchive.cpp
  SFileOpenFileEx.cpp
  SFileReadFile.cpp
  SListFile.cpp
  StormDll.h
  StormLib.h
  StormPort.h
  StormPortLinux.cpp
  StormPortMac.cpp