[8423] Fixed typo in mangos.sql.
[getmangos.git] / contrib / vmap_extractor_v2 / stormlib / SFileFindFile.cpp
blob41dbeba900cad445edf7da0af56e6840182b172e
1 /*****************************************************************************/
2 /* SFileFindFile.cpp Copyright (c) Ladislav Zezula 2003 */
3 /*---------------------------------------------------------------------------*/
4 /* A module for file searching within MPQs */
5 /*---------------------------------------------------------------------------*/
6 /* Date Ver Who Comment */
7 /* -------- ---- --- ------- */
8 /* 25.03.03 1.00 Lad The first version of SFileFindFile.cpp */
9 /*****************************************************************************/
11 #define __STORMLIB_SELF__
12 #include "StormLib.h"
13 #include "SCommon.h"
15 //-----------------------------------------------------------------------------
16 // Defines
18 #define LISTFILE_CACHE_SIZE 0x1000
20 //-----------------------------------------------------------------------------
21 // Local functions
23 static BOOL IsValidSearchHandle(TMPQSearch * hs)
25 if(hs == NULL || IsBadReadPtr(hs, sizeof(TMPQSearch)))
26 return FALSE;
28 if(!IsValidMpqHandle(hs->ha))
29 return FALSE;
31 return TRUE;
34 // This function compares a string with a wildcard search string.
35 // returns TRUE, when the string matches with the wildcard.
36 BOOL CheckWildCard(const char * szString, const char * szWildCard)
38 char * szTemp; // Temporary helper pointer
39 int nResult = 0; // For memcmp return values
40 int nMustNotMatch = 0; // Number of following chars int szString,
41 // which must not match with szWildCard
42 int nMustMatch = 0; // Number of the following characters,
43 // which must match
45 // When the string is empty, it does not match with every wildcard
46 if(*szString == 0)
47 return FALSE;
49 // When the mask is empty, it matches to every wildcard
50 if(szWildCard == NULL || *szWildCard == 0)
51 return FALSE;
53 // Do normal test
54 for(;;)
56 switch(*szWildCard)
58 case '*': // Means "every number of characters"
59 // Skip all asterisks
60 while(*szWildCard == '*')
61 szWildCard++;
63 // When no more characters in wildcard, it means that the strings match
64 if(*szWildCard == 0)
65 return TRUE;
67 // The next N characters must not agree
68 nMustNotMatch |= 0x70000000;
69 break;
71 case '?': // Means "One or no character"
72 while(*szWildCard == '?')
74 nMustNotMatch++;
75 szWildCard++;
77 break;
79 default:
80 // If the two characters match
81 if(toupper(*szString) == toupper(*szWildCard))
83 // When end of string, they agree
84 if(*szString == 0)
85 return TRUE;
87 nMustNotMatch = 0;
88 szWildCard++;
89 szString++;
90 break;
93 // If the next character must match, the string does not match
94 if(nMustNotMatch == 0)
95 return FALSE;
97 // Count the characters which must match after characters
98 // that must not match
99 szTemp = (char *)szWildCard;
100 nMustMatch = 0;
101 while(*szTemp != 0 && *szTemp != '*' && *szTemp != '?')
103 nMustMatch++;
104 szTemp++;
107 // Now skip characters from szString up to number of chars
108 // that must not match
109 nResult = -1;
110 while(nMustNotMatch > 0 && *szString != 0)
112 if((nResult = _strnicmp(szString, szWildCard, nMustMatch)) == 0)
113 break;
115 szString++;
116 nMustNotMatch--;
119 // Make one more comparison
120 if(nMustNotMatch == 0)
121 nResult = _strnicmp(szString, szWildCard, nMustMatch);
123 // If a match has been found, continue the search
124 if(nResult == 0)
126 nMustNotMatch = 0;
127 szWildCard += nMustMatch;
128 szString += nMustMatch;
129 break;
131 return FALSE;
136 // Performs one MPQ search
137 // TODO: Test for archives > 4GB
138 static int DoMPQSearch(TMPQSearch * hs, SFILE_FIND_DATA * lpFindFileData)
140 TMPQArchive * ha = hs->ha;
141 TFileNode * pNode;
142 TMPQHash * pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize;
143 TMPQHash * pHash = ha->pHashTable + hs->dwNextIndex;
145 // Do until some file found or no more files
146 while(pHash < pHashEnd)
148 pNode = ha->pListFile[hs->dwNextIndex++];
150 // If this entry is free, do nothing
151 if(pHash->dwBlockIndex < HASH_ENTRY_FREE && (DWORD_PTR)pNode < HASH_ENTRY_FREE)
153 // Check the file name.
154 if(CheckWildCard(pNode->szFileName, hs->szSearchMask))
156 TMPQBlock * pBlock = ha->pBlockTable + pHash->dwBlockIndex;
158 lpFindFileData->lcLocale = pHash->lcLocale;
159 lpFindFileData->dwFileSize = pBlock->dwFSize;
160 lpFindFileData->dwFileFlags = pBlock->dwFlags;
161 lpFindFileData->dwBlockIndex = pHash->dwBlockIndex;
162 lpFindFileData->dwCompSize = pBlock->dwCSize;
164 // Fill the file name and plain file name
165 strcpy(lpFindFileData->cFileName, pNode->szFileName);
166 lpFindFileData->szPlainName = strrchr(lpFindFileData->cFileName, '\\');
167 if(lpFindFileData->szPlainName == NULL)
168 lpFindFileData->szPlainName = lpFindFileData->cFileName;
169 else
170 lpFindFileData->szPlainName++;
172 // Fill the next entry
173 return ERROR_SUCCESS;
177 pHash++;
180 // No more files found, return error
181 return ERROR_NO_MORE_FILES;
184 // TODO: Test for archives > 4GB
185 static void FreeMPQSearch(TMPQSearch *& hs)
187 if(hs != NULL)
189 FREEMEM(hs);
190 hs = NULL;
194 //-----------------------------------------------------------------------------
195 // Public functions
197 // TODO: Test for archives > 4GB
198 HANDLE WINAPI SFileFindFirstFile(HANDLE hMPQ, const char * szMask, SFILE_FIND_DATA * lpFindFileData, const char * szListFile)
200 TMPQArchive * ha = (TMPQArchive *)hMPQ;
201 TMPQSearch * hs = NULL; // Search object handle
202 size_t nSize = 0;
203 int nError = ERROR_SUCCESS;
205 // Check for the valid parameters
206 if(nError == ERROR_SUCCESS)
208 if(!IsValidMpqHandle(ha))
209 nError = ERROR_INVALID_PARAMETER;
211 if(szMask == NULL || lpFindFileData == NULL)
212 nError = ERROR_INVALID_PARAMETER;
214 if(szListFile == NULL && !IsValidMpqHandle(ha))
215 nError = ERROR_INVALID_PARAMETER;
218 // Include the listfile into the MPQ's internal listfile
219 // Note that if the listfile name is NULL, do nothing because the
220 // internal listfile is always included.
221 if(nError == ERROR_SUCCESS && szListFile != NULL)
222 nError = SFileAddListFile((HANDLE)ha, szListFile);
224 // Allocate the structure for MPQ search
225 if(nError == ERROR_SUCCESS)
227 nSize = sizeof(TMPQSearch) + strlen(szMask) + 1;
228 if((hs = (TMPQSearch *)ALLOCMEM(char, nSize)) == NULL)
229 nError = ERROR_NOT_ENOUGH_MEMORY;
232 // Perform the first search
233 if(nError == ERROR_SUCCESS)
235 memset(hs, 0, sizeof(TMPQSearch));
236 hs->ha = ha;
237 hs->dwNextIndex = 0;
238 strcpy(hs->szSearchMask, szMask);
239 nError = DoMPQSearch(hs, lpFindFileData);
242 // Cleanup
243 if(nError != ERROR_SUCCESS)
245 FreeMPQSearch(hs);
246 SetLastError(nError);
249 // Return the result value
250 return (HANDLE)hs;
253 // TODO: Test for archives > 4GB
254 BOOL WINAPI SFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData)
256 TMPQSearch * hs = (TMPQSearch *)hFind;
257 int nError = ERROR_SUCCESS;
259 // Check the parameters
260 if(nError == ERROR_SUCCESS)
262 if(!IsValidSearchHandle(hs) || lpFindFileData == NULL)
263 nError = ERROR_INVALID_PARAMETER;
266 if(nError == ERROR_SUCCESS)
267 nError = DoMPQSearch(hs, lpFindFileData);
269 if(nError != ERROR_SUCCESS)
271 SetLastError(nError);
272 return FALSE;
274 return TRUE;
277 // TODO: Test for archives > 4GB
278 BOOL WINAPI SFileFindClose(HANDLE hFind)
280 TMPQSearch * hs = (TMPQSearch *)hFind;
282 // Check the parameters
283 if(!IsValidSearchHandle(hs))
285 SetLastError(ERROR_INVALID_PARAMETER);
286 return FALSE;
289 FreeMPQSearch(hs);
290 return TRUE;