TrinityCore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
CascLib.h File Reference
#include "CascPort.h"
+ Include dependency graph for CascLib.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  _QUERY_KEY
 
struct  _CASC_FIND_DATA
 

Macros

#define CASCLIB_VERSION   0x0100
 
#define CASCLIB_VERSION_STRING   "1.00"
 
#define ERROR_UNKNOWN_FILE_KEY   10001
 
#define ERROR_FILE_INCOMPLETE   10006
 
#define CASC_STOR_XXXXX   0x00000001
 
#define CASC_OPEN_BY_ENCODING_KEY   0x00000001
 
#define BASE_PROVIDER_FILE   0x00000000
 
#define BASE_PROVIDER_MAP   0x00000001
 
#define BASE_PROVIDER_HTTP   0x00000002
 
#define BASE_PROVIDER_MASK   0x0000000F
 
#define STREAM_PROVIDER_FLAT   0x00000000
 
#define STREAM_PROVIDER_PARTIAL   0x00000010
 
#define STREAM_PROVIDER_ENCRYPTED   0x00000020
 
#define STREAM_PROVIDER_BLOCK4   0x00000030
 
#define STREAM_PROVIDER_MASK   0x000000F0
 
#define STREAM_FLAG_READ_ONLY   0x00000100
 
#define STREAM_FLAG_WRITE_SHARE   0x00000200
 
#define STREAM_FLAG_USE_BITMAP   0x00000400
 
#define STREAM_OPTIONS_MASK   0x0000FF00
 
#define STREAM_PROVIDERS_MASK   0x000000FF
 
#define STREAM_FLAGS_MASK   0x0000FFFF
 
#define CASC_LOCALE_ALL   0xFFFFFFFF
 
#define CASC_LOCALE_NONE   0x00000000
 
#define CASC_LOCALE_UNKNOWN1   0x00000001
 
#define CASC_LOCALE_ENUS   0x00000002
 
#define CASC_LOCALE_KOKR   0x00000004
 
#define CASC_LOCALE_RESERVED   0x00000008
 
#define CASC_LOCALE_FRFR   0x00000010
 
#define CASC_LOCALE_DEDE   0x00000020
 
#define CASC_LOCALE_ZHCN   0x00000040
 
#define CASC_LOCALE_ESES   0x00000080
 
#define CASC_LOCALE_ZHTW   0x00000100
 
#define CASC_LOCALE_ENGB   0x00000200
 
#define CASC_LOCALE_ENCN   0x00000400
 
#define CASC_LOCALE_ENTW   0x00000800
 
#define CASC_LOCALE_ESMX   0x00001000
 
#define CASC_LOCALE_RURU   0x00002000
 
#define CASC_LOCALE_PTBR   0x00004000
 
#define CASC_LOCALE_ITIT   0x00008000
 
#define CASC_LOCALE_PTPT   0x00010000
 
#define CASC_LOCALE_BIT_ENUS   0x01
 
#define CASC_LOCALE_BIT_KOKR   0x02
 
#define CASC_LOCALE_DUAL_LANG   0x03
 
#define CASC_LOCALE_BIT_FRFR   0x04
 
#define CASC_LOCALE_BIT_DEDE   0x05
 
#define CASC_LOCALE_BIT_ZHCN   0x06
 
#define CASC_LOCALE_BIT_ESES   0x07
 
#define CASC_LOCALE_BIT_ZHTW   0x08
 
#define CASC_LOCALE_BIT_ENGB   0x09
 
#define CASC_LOCALE_BIT_ENCN   0x0A
 
#define CASC_LOCALE_BIT_ENTW   0x0B
 
#define CASC_LOCALE_BIT_ESMX   0x0C
 
#define CASC_LOCALE_BIT_RURU   0x0D
 
#define CASC_LOCALE_BIT_PTBR   0x0E
 
#define CASC_LOCALE_BIT_ITIT   0x0F
 
#define CASC_LOCALE_BIT_PTPT   0x10
 
#define MAX_CASC_KEY_LENGTH   0x10
 
#define MD5_HASH_SIZE   0x10
 
#define MD5_STRING_SIZE   0x20
 
#define SHA1_DIGEST_SIZE   0x14
 
#define LANG_NEUTRAL   0x00
 
#define CASC_INVALID_SIZE   0xFFFFFFFF
 
#define CASC_INVALID_POS   0xFFFFFFFF
 
#define CASC_FEATURE_LISTFILE   0x00000001
 

Typedefs

typedef enum
_CASC_STORAGE_INFO_CLASS 
CASC_STORAGE_INFO_CLASS
 
typedef enum
_CASC_STORAGE_INFO_CLASS
PCASC_STORAGE_INFO_CLASS
 
typedef struct _QUERY_KEY QUERY_KEY
 
typedef struct _QUERY_KEYPQUERY_KEY
 
typedef struct _CASC_FIND_DATA CASC_FIND_DATA
 
typedef struct _CASC_FIND_DATAPCASC_FIND_DATA
 
typedef struct TFileStream TFileStream
 
typedef void(WINAPISTREAM_DOWNLOAD_CALLBACK )(void *pvUserData, ULONGLONG ByteOffset, DWORD dwTotalBytes)
 

Enumerations

enum  _CASC_STORAGE_INFO_CLASS {
  CascStorageFileCount, CascStorageFeatures, CascStorageGameInfo, CascStorageGameBuild,
  CascStorageInfoClassMax
}
 

Functions

void qsort_pointer_array (void **base, size_t num, int(*compare)(const void *, const void *, const void *), const void *context)
 
bool WINAPI CascOpenStorage (const TCHAR *szDataPath, DWORD dwLocaleMask, HANDLE *phStorage)
 
bool WINAPI CascGetStorageInfo (HANDLE hStorage, CASC_STORAGE_INFO_CLASS InfoClass, void *pvStorageInfo, size_t cbStorageInfo, size_t *pcbLengthNeeded)
 
bool WINAPI CascCloseStorage (HANDLE hStorage)
 
bool WINAPI CascOpenFileByIndexKey (HANDLE hStorage, PQUERY_KEY pIndexKey, DWORD dwFlags, HANDLE *phFile)
 
bool WINAPI CascOpenFileByEncodingKey (HANDLE hStorage, PQUERY_KEY pEncodingKey, DWORD dwFlags, HANDLE *phFile)
 
bool WINAPI CascOpenFile (HANDLE hStorage, const char *szFileName, DWORD dwLocale, DWORD dwFlags, HANDLE *phFile)
 
DWORD WINAPI CascGetFileSize (HANDLE hFile, PDWORD pdwFileSizeHigh)
 
DWORD WINAPI CascSetFilePointer (HANDLE hFile, LONG lFilePos, LONG *plFilePosHigh, DWORD dwMoveMethod)
 
bool WINAPI CascReadFile (HANDLE hFile, void *lpBuffer, DWORD dwToRead, PDWORD pdwRead)
 
bool WINAPI CascCloseFile (HANDLE hFile)
 
HANDLE WINAPI CascFindFirstFile (HANDLE hStorage, const char *szMask, PCASC_FIND_DATA pFindData, const TCHAR *szListFile)
 
bool WINAPI CascFindNextFile (HANDLE hFind, PCASC_FIND_DATA pFindData)
 
bool WINAPI CascFindClose (HANDLE hFind)
 
int GetLastError ()
 
void SetLastError (int nError)
 

Macro Definition Documentation

#define BASE_PROVIDER_FILE   0x00000000
#define BASE_PROVIDER_HTTP   0x00000002
#define BASE_PROVIDER_MAP   0x00000001
#define BASE_PROVIDER_MASK   0x0000000F
#define CASC_FEATURE_LISTFILE   0x00000001
#define CASC_INVALID_POS   0xFFFFFFFF
#define CASC_INVALID_SIZE   0xFFFFFFFF
#define CASC_LOCALE_ALL   0xFFFFFFFF
#define CASC_LOCALE_BIT_DEDE   0x05
#define CASC_LOCALE_BIT_ENCN   0x0A
#define CASC_LOCALE_BIT_ENGB   0x09
#define CASC_LOCALE_BIT_ENTW   0x0B
#define CASC_LOCALE_BIT_ENUS   0x01
#define CASC_LOCALE_BIT_ESES   0x07
#define CASC_LOCALE_BIT_ESMX   0x0C
#define CASC_LOCALE_BIT_FRFR   0x04
#define CASC_LOCALE_BIT_ITIT   0x0F
#define CASC_LOCALE_BIT_KOKR   0x02
#define CASC_LOCALE_BIT_PTBR   0x0E
#define CASC_LOCALE_BIT_PTPT   0x10
#define CASC_LOCALE_BIT_RURU   0x0D
#define CASC_LOCALE_BIT_ZHCN   0x06
#define CASC_LOCALE_BIT_ZHTW   0x08
#define CASC_LOCALE_DEDE   0x00000020
#define CASC_LOCALE_DUAL_LANG   0x03
#define CASC_LOCALE_ENCN   0x00000400
#define CASC_LOCALE_ENGB   0x00000200
#define CASC_LOCALE_ENTW   0x00000800
#define CASC_LOCALE_ENUS   0x00000002
#define CASC_LOCALE_ESES   0x00000080
#define CASC_LOCALE_ESMX   0x00001000
#define CASC_LOCALE_FRFR   0x00000010
#define CASC_LOCALE_ITIT   0x00008000
#define CASC_LOCALE_KOKR   0x00000004
#define CASC_LOCALE_NONE   0x00000000
#define CASC_LOCALE_PTBR   0x00004000
#define CASC_LOCALE_PTPT   0x00010000
#define CASC_LOCALE_RESERVED   0x00000008
#define CASC_LOCALE_RURU   0x00002000
#define CASC_LOCALE_UNKNOWN1   0x00000001
#define CASC_LOCALE_ZHCN   0x00000040
#define CASC_LOCALE_ZHTW   0x00000100
#define CASC_OPEN_BY_ENCODING_KEY   0x00000001
#define CASC_STOR_XXXXX   0x00000001
#define CASCLIB_VERSION   0x0100
#define CASCLIB_VERSION_STRING   "1.00"
#define ERROR_FILE_INCOMPLETE   10006
#define ERROR_UNKNOWN_FILE_KEY   10001
#define LANG_NEUTRAL   0x00
#define MAX_CASC_KEY_LENGTH   0x10
#define MD5_HASH_SIZE   0x10
#define MD5_STRING_SIZE   0x20
#define SHA1_DIGEST_SIZE   0x14
#define STREAM_FLAG_READ_ONLY   0x00000100
#define STREAM_FLAG_USE_BITMAP   0x00000400
#define STREAM_FLAG_WRITE_SHARE   0x00000200
#define STREAM_FLAGS_MASK   0x0000FFFF
#define STREAM_OPTIONS_MASK   0x0000FF00
#define STREAM_PROVIDER_BLOCK4   0x00000030
#define STREAM_PROVIDER_ENCRYPTED   0x00000020
#define STREAM_PROVIDER_FLAT   0x00000000
#define STREAM_PROVIDER_MASK   0x000000F0
#define STREAM_PROVIDER_PARTIAL   0x00000010
#define STREAM_PROVIDERS_MASK   0x000000FF

Typedef Documentation

typedef struct _CASC_FIND_DATA * PCASC_FIND_DATA
typedef struct _QUERY_KEY * PQUERY_KEY
typedef struct _QUERY_KEY QUERY_KEY
typedef void(WINAPI * STREAM_DOWNLOAD_CALLBACK)(void *pvUserData, ULONGLONG ByteOffset, DWORD dwTotalBytes)
typedef struct TFileStream TFileStream

Enumeration Type Documentation

Enumerator
CascStorageFileCount 
CascStorageFeatures 
CascStorageGameInfo 
CascStorageGameBuild 
CascStorageInfoClassMax 
128 {
134 
Definition: CascLib.h:131
Definition: CascLib.h:132
Definition: CascLib.h:129
Definition: CascLib.h:130
enum _CASC_STORAGE_INFO_CLASS * PCASC_STORAGE_INFO_CLASS
enum _CASC_STORAGE_INFO_CLASS CASC_STORAGE_INFO_CLASS
Definition: CascLib.h:133

Function Documentation

bool WINAPI CascCloseFile ( HANDLE  hFile)
274 {
275  TCascFile * hf;
276 
277  hf = IsValidFileHandle(hFile);
278  if(hf != NULL)
279  {
280  // Close (dereference) the archive handle
281  if(hf->hs != NULL)
282  CascCloseStorage((HANDLE)hf->hs);
283  hf->hs = NULL;
284 
285  // Free the file cache and frame array
286  if(hf->pbFileCache != NULL)
287  CASC_FREE(hf->pbFileCache);
288  if(hf->pFrames != NULL)
289  CASC_FREE(hf->pFrames);
290 
291  // Free the structure itself
292  hf->szClassName = NULL;
293  CASC_FREE(hf);
294  return true;
295  }
296 
298  return false;
299 }
const char * szClassName
Definition: CascCommon.h:231
void * HANDLE
Definition: CascPort.h:146
TCascFile * IsValidFileHandle(HANDLE hFile)
Definition: CascOpenFile.cpp:18
arena_t NULL
Definition: jemalloc_internal.h:624
LPBYTE pbFileCache
Definition: CascCommon.h:246
#define CASC_FREE(ptr)
Definition: CascCommon.h:303
#define ERROR_INVALID_HANDLE
Definition: CascPort.h:207
bool WINAPI CascCloseStorage(HANDLE hStorage)
Definition: CascOpenStorage.cpp:1133
void SetLastError(int nError)
Definition: Common.cpp:75
PCASC_FILE_FRAME pFrames
Definition: CascCommon.h:243
TCascStorage * hs
Definition: CascCommon.h:229
Definition: CascCommon.h:227

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool WINAPI CascCloseStorage ( HANDLE  hStorage)
1134 {
1135  TCascStorage * hs;
1136 
1137  // Verify the storage handle
1138  hs = IsValidStorageHandle(hStorage);
1139  if(hs == NULL)
1140  {
1142  return false;
1143  }
1144 
1145  // Only free the storage if the reference count reaches 0
1146  if(hs->dwRefCount == 1)
1147  {
1148  FreeCascStorage(hs);
1149  return true;
1150  }
1151 
1152  // Just decrement number of references
1153  hs->dwRefCount--;
1154  return true;
1155 }
TCascStorage * IsValidStorageHandle(HANDLE hStorage)
Definition: CascOpenStorage.cpp:100
arena_t NULL
Definition: jemalloc_internal.h:624
void SetLastError(int nError)
Definition: Common.cpp:75
Definition: CascCommon.h:186
DWORD dwRefCount
Definition: CascCommon.h:195
#define ERROR_INVALID_PARAMETER
Definition: CascPort.h:210
static TCascStorage * FreeCascStorage(TCascStorage *hs)
Definition: CascOpenStorage.cpp:934

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool WINAPI CascFindClose ( HANDLE  hFind)
311 {
312  TCascSearch * pSearch;
313 
314  pSearch = IsValidSearchHandle(hFind);
315  if(pSearch == NULL)
316  {
318  return false;
319  }
320 
321  FreeSearchHandle(pSearch);
322  return true;
323 }
arena_t NULL
Definition: jemalloc_internal.h:624
void SetLastError(int nError)
Definition: Common.cpp:75
Definition: CascCommon.h:261
#define ERROR_INVALID_PARAMETER
Definition: CascPort.h:210
static TCascSearch * IsValidSearchHandle(HANDLE hFind)
Definition: CascFindFile.cpp:18
static void FreeSearchHandle(TCascSearch *pSearch)
Definition: CascFindFile.cpp:25

+ Here is the call graph for this function:

HANDLE WINAPI CascFindFirstFile ( HANDLE  hStorage,
const char *  szMask,
PCASC_FIND_DATA  pFindData,
const TCHAR szListFile 
)
253 {
254  TCascStorage * hs;
255  TCascSearch * pSearch = NULL;
256  int nError = ERROR_SUCCESS;
257 
258  // Check parameters
259  if((hs = IsValidStorageHandle(hStorage)) == NULL)
260  nError = ERROR_INVALID_HANDLE;
261  if(szMask == NULL || pFindData == NULL)
262  nError = ERROR_INVALID_PARAMETER;
263 
264  // Init the search structure and search handle
265  if(nError == ERROR_SUCCESS)
266  {
267  // Clear the entire search structure
268  memset(pFindData, 0, sizeof(CASC_FIND_DATA));
269 
270  // Allocate the search handle
271  pSearch = AllocateSearchHandle(hs, szListFile, szMask);
272  if(pSearch == NULL)
273  nError = ERROR_NOT_ENOUGH_MEMORY;
274  }
275 
276  // Perform search
277  if(nError == ERROR_SUCCESS)
278  {
279  if(!DoStorageSearch(pSearch, pFindData))
280  nError = ERROR_NO_MORE_FILES;
281  }
282 
283  if(nError != ERROR_SUCCESS)
284  {
285  if(pSearch != NULL)
286  FreeSearchHandle(pSearch);
287  pSearch = NULL;
288  }
289 
290  return (HANDLE)pSearch;
291 }
static bool DoStorageSearch(TCascSearch *pSearch, PCASC_FIND_DATA pFindData)
Definition: CascFindFile.cpp:207
void * HANDLE
Definition: CascPort.h:146
#define ERROR_NOT_ENOUGH_MEMORY
Definition: CascPort.h:208
arena_t NULL
Definition: jemalloc_internal.h:624
#define ERROR_NO_MORE_FILES
Definition: CascPort.h:215
Definition: CascLib.h:145
#define ERROR_INVALID_HANDLE
Definition: CascPort.h:207
static TCascSearch * AllocateSearchHandle(TCascStorage *hs, const TCHAR *szListFile, const char *szMask)
Definition: CascFindFile.cpp:56
Definition: CascCommon.h:186
Definition: CascCommon.h:261
#define ERROR_INVALID_PARAMETER
Definition: CascPort.h:210
TCascStorage * IsValidStorageHandle(HANDLE hStorage)
Definition: CascOpenStorage.cpp:100
static void FreeSearchHandle(TCascSearch *pSearch)
Definition: CascFindFile.cpp:25
#define ERROR_SUCCESS
Definition: CascPort.h:204

+ Here is the call graph for this function:

bool WINAPI CascFindNextFile ( HANDLE  hFind,
PCASC_FIND_DATA  pFindData 
)
296 {
297  TCascSearch * pSearch;
298 
299  pSearch = IsValidSearchHandle(hFind);
300  if(pSearch == NULL || pFindData == NULL)
301  {
303  return false;
304  }
305 
306  // Perform search
307  return DoStorageSearch(pSearch, pFindData);
308 }
static bool DoStorageSearch(TCascSearch *pSearch, PCASC_FIND_DATA pFindData)
Definition: CascFindFile.cpp:207
arena_t NULL
Definition: jemalloc_internal.h:624
void SetLastError(int nError)
Definition: Common.cpp:75
Definition: CascCommon.h:261
#define ERROR_INVALID_PARAMETER
Definition: CascPort.h:210
static TCascSearch * IsValidSearchHandle(HANDLE hFind)
Definition: CascFindFile.cpp:18

+ Here is the call graph for this function:

DWORD WINAPI CascGetFileSize ( HANDLE  hFile,
PDWORD  pdwFileSizeHigh 
)
368 {
369  TCascFile * hf;
370  int nError;
371 
372  CASCLIB_UNUSED(pdwFileSizeHigh);
373 
374  // Validate the file handle
375  if((hf = IsValidFileHandle(hFile)) == NULL)
376  {
378  return CASC_INVALID_SIZE;
379  }
380 
381  // Make sure that the file header area is loaded
382  nError = EnsureFrameHeadersLoaded(hf);
383  if(nError != ERROR_SUCCESS)
384  {
385  SetLastError(nError);
386  return CASC_INVALID_SIZE;
387  }
388 
389  // Give the file size to the caller
390  if(pdwFileSizeHigh != NULL)
391  *pdwFileSizeHigh = 0;
392  return hf->FileSize;
393 }
arena_t NULL
Definition: jemalloc_internal.h:624
DWORD FileSize
Definition: CascCommon.h:240
#define CASCLIB_UNUSED(p)
Definition: CascCommon.h:75
static int EnsureFrameHeadersLoaded(TCascFile *hf)
Definition: CascReadFile.cpp:202
#define ERROR_INVALID_HANDLE
Definition: CascPort.h:207
void SetLastError(int nError)
Definition: Common.cpp:75
#define CASC_INVALID_SIZE
Definition: CascLib.h:118
TCascFile * IsValidFileHandle(HANDLE hFile)
Definition: CascOpenFile.cpp:18
Definition: CascCommon.h:227
#define ERROR_SUCCESS
Definition: CascPort.h:204

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool WINAPI CascGetStorageInfo ( HANDLE  hStorage,
CASC_STORAGE_INFO_CLASS  InfoClass,
void *  pvStorageInfo,
size_t  cbStorageInfo,
size_t *  pcbLengthNeeded 
)
1081 {
1082  TCascStorage * hs;
1083  DWORD dwInfoValue = 0;
1084 
1085  // Verify the storage handle
1086  hs = IsValidStorageHandle(hStorage);
1087  if(hs == NULL)
1088  {
1090  return false;
1091  }
1092 
1093  // Differentiate between info classes
1094  switch(InfoClass)
1095  {
1096  case CascStorageFileCount:
1097  dwInfoValue = (DWORD)hs->pIndexEntryMap->ItemCount;
1098  break;
1099 
1100  case CascStorageFeatures:
1101  dwInfoValue |= (hs->pRootHandler->dwRootFlags & ROOT_FLAG_HAS_NAMES) ? CASC_FEATURE_LISTFILE : 0;
1102  break;
1103 
1104  case CascStorageGameInfo:
1105  dwInfoValue = hs->dwGameInfo;
1106  break;
1107 
1108  case CascStorageGameBuild:
1109  dwInfoValue = hs->dwBuildNumber;
1110  break;
1111 
1112  default:
1114  return false;
1115  }
1116 
1117  //
1118  // Return the required DWORD value
1119  //
1120 
1121  if(cbStorageInfo < sizeof(DWORD))
1122  {
1123  *pcbLengthNeeded = sizeof(DWORD);
1125  return false;
1126  }
1127 
1128  // Give the number of files
1129  *(PDWORD)pvStorageInfo = dwInfoValue;
1130  return true;
1131 }
TRootHandler * pRootHandler
Definition: CascCommon.h:223
Definition: CascLib.h:131
Definition: CascLib.h:132
DWORD * PDWORD
Definition: CascPort.h:151
TCascStorage * IsValidStorageHandle(HANDLE hStorage)
Definition: CascOpenStorage.cpp:100
DWORD dwRootFlags
Definition: RootHandler.h:75
#define ERROR_INSUFFICIENT_BUFFER
Definition: CascPort.h:213
#define ROOT_FLAG_HAS_NAMES
Definition: RootHandler.h:21
PCASC_MAP pIndexEntryMap
Definition: CascCommon.h:217
arena_t NULL
Definition: jemalloc_internal.h:624
Definition: CascLib.h:129
#define ERROR_INVALID_HANDLE
Definition: CascPort.h:207
Definition: CascLib.h:130
void SetLastError(int nError)
Definition: Common.cpp:75
Definition: CascCommon.h:186
DWORD dwGameInfo
Definition: CascCommon.h:196
unsigned int DWORD
Definition: CascPort.h:139
#define ERROR_INVALID_PARAMETER
Definition: CascPort.h:210
size_t ItemCount
Definition: Map.h:22
#define CASC_FEATURE_LISTFILE
Definition: CascLib.h:122
DWORD dwBuildNumber
Definition: CascCommon.h:197

+ Here is the call graph for this function:

bool WINAPI CascOpenFile ( HANDLE  hStorage,
const char *  szFileName,
DWORD  dwLocale,
DWORD  dwFlags,
HANDLE phFile 
)
197 {
198  TCascStorage * hs;
199  QUERY_KEY EncodingKey;
200  LPBYTE pbEncodingKey;
201  BYTE KeyBuffer[MD5_HASH_SIZE];
202  int nError = ERROR_SUCCESS;
203 
204  CASCLIB_UNUSED(dwLocale);
205 
206  // Validate the storage handle
207  hs = IsValidStorageHandle(hStorage);
208  if(hs == NULL)
209  {
211  return false;
212  }
213 
214  // Validate the other parameters
215  if(szFileName == NULL || szFileName[0] == 0 || phFile == NULL)
216  {
218  return false;
219  }
220 
221  // If the user is opening the file via encoding key, skip the ROOT file processing
222  if((dwFlags & CASC_OPEN_BY_ENCODING_KEY) == 0)
223  {
224  // Let the root directory provider get us the encoding key
225  pbEncodingKey = RootHandler_GetKey(hs->pRootHandler, szFileName);
226  if(pbEncodingKey == NULL)
227  {
229  return false;
230  }
231 
232  // Setup the encoding key
233  EncodingKey.pbData = pbEncodingKey;
234  EncodingKey.cbData = MD5_HASH_SIZE;
235  }
236  else
237  {
238  // Check the length of the file name
239  if(strlen(szFileName) < MD5_STRING_SIZE)
240  {
242  return false;
243  }
244 
245  // Convert the file name to binary blob
246  EncodingKey.pbData = KeyBuffer;
247  EncodingKey.cbData = MD5_HASH_SIZE;
248  nError = ConvertStringToBinary(szFileName, MD5_STRING_SIZE, KeyBuffer);
249  }
250 
251  // Use the encoding key to find the file in the encoding table entry
252  if(nError == ERROR_SUCCESS)
253  {
254  if(!OpenFileByEncodingKey(hs, &EncodingKey, dwFlags, (TCascFile **)phFile))
255  {
256  assert(GetLastError() != ERROR_SUCCESS);
257  nError = GetLastError();
258  }
259  }
260 
261 #ifdef CASCLIB_TEST
262 // if(phFile[0] != NULL && pRootEntryMndx != NULL)
263 // {
264 // ((TCascFile *)(phFile[0]))->FileSize_RootEntry = pRootEntryMndx->FileSize;
265 // }
266 #endif
267 
268  if(nError != ERROR_SUCCESS)
269  SetLastError(nError);
270  return (nError == ERROR_SUCCESS);
271 }
TRootHandler * pRootHandler
Definition: CascCommon.h:223
int ConvertStringToBinary(const char *szString, size_t nMaxDigits, LPBYTE pbBinary)
Definition: Common.cpp:338
Definition: CascLib.h:138
arena_t NULL
Definition: jemalloc_internal.h:624
#define CASCLIB_UNUSED(p)
Definition: CascCommon.h:75
BYTE * LPBYTE
Definition: CascPort.h:152
static bool OpenFileByEncodingKey(TCascStorage *hs, PQUERY_KEY pEncodingKey, DWORD dwFlags, TCascFile **ppCascFile)
Definition: CascOpenFile.cpp:110
DWORD cbData
Definition: CascLib.h:141
#define ERROR_INVALID_HANDLE
Definition: CascPort.h:207
LPBYTE RootHandler_GetKey(TRootHandler *pRootHandler, const char *szFileName)
Definition: RootHandler.cpp:44
#define MD5_HASH_SIZE
Definition: CascLib.h:105
void SetLastError(int nError)
Definition: Common.cpp:75
#define ERROR_FILE_NOT_FOUND
Definition: CascPort.h:205
Definition: CascCommon.h:186
LPBYTE pbData
Definition: CascLib.h:140
int GetLastError()
Definition: Common.cpp:70
#define ERROR_INVALID_PARAMETER
Definition: CascPort.h:210
unsigned char BYTE
Definition: CascPort.h:136
Definition: CascCommon.h:227
#define MD5_STRING_SIZE
Definition: CascLib.h:106
TCascStorage * IsValidStorageHandle(HANDLE hStorage)
Definition: CascOpenStorage.cpp:100
#define CASC_OPEN_BY_ENCODING_KEY
Definition: CascLib.h:42
#define ERROR_SUCCESS
Definition: CascPort.h:204

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool WINAPI CascOpenFileByEncodingKey ( HANDLE  hStorage,
PQUERY_KEY  pEncodingKey,
DWORD  dwFlags,
HANDLE phFile 
)
174 {
175  TCascStorage * hs;
176 
177  // Validate the storage handle
178  hs = IsValidStorageHandle(hStorage);
179  if(hs == NULL)
180  {
182  return false;
183  }
184 
185  // Validate the other parameters
186  if(pEncodingKey == NULL || pEncodingKey->pbData == NULL || pEncodingKey->cbData == 0 || phFile == NULL)
187  {
189  return false;
190  }
191 
192  // Use the internal function fo open the file
193  return OpenFileByEncodingKey(hs, pEncodingKey, dwFlags, (TCascFile **)phFile);
194 }
arena_t NULL
Definition: jemalloc_internal.h:624
static bool OpenFileByEncodingKey(TCascStorage *hs, PQUERY_KEY pEncodingKey, DWORD dwFlags, TCascFile **ppCascFile)
Definition: CascOpenFile.cpp:110
DWORD cbData
Definition: CascLib.h:141
#define ERROR_INVALID_HANDLE
Definition: CascPort.h:207
void SetLastError(int nError)
Definition: Common.cpp:75
Definition: CascCommon.h:186
LPBYTE pbData
Definition: CascLib.h:140
#define ERROR_INVALID_PARAMETER
Definition: CascPort.h:210
Definition: CascCommon.h:227
TCascStorage * IsValidStorageHandle(HANDLE hStorage)
Definition: CascOpenStorage.cpp:100

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool WINAPI CascOpenFileByIndexKey ( HANDLE  hStorage,
PQUERY_KEY  pIndexKey,
DWORD  dwFlags,
HANDLE phFile 
)
151 {
152  TCascStorage * hs;
153 
154  // Validate the storage handle
155  hs = IsValidStorageHandle(hStorage);
156  if(hs == NULL)
157  {
159  return false;
160  }
161 
162  // Validate the other parameters
163  if(pIndexKey == NULL || pIndexKey->pbData == NULL || pIndexKey->cbData == 0 || phFile == NULL)
164  {
166  return false;
167  }
168 
169  // Use the internal function to open the file
170  return OpenFileByIndexKey(hs, pIndexKey, dwFlags, (TCascFile **)phFile);
171 }
arena_t NULL
Definition: jemalloc_internal.h:624
DWORD cbData
Definition: CascLib.h:141
#define ERROR_INVALID_HANDLE
Definition: CascPort.h:207
void SetLastError(int nError)
Definition: Common.cpp:75
Definition: CascCommon.h:186
LPBYTE pbData
Definition: CascLib.h:140
static bool OpenFileByIndexKey(TCascStorage *hs, PQUERY_KEY pIndexKey, DWORD dwFlags, TCascFile **ppCascFile)
Definition: CascOpenFile.cpp:78
#define ERROR_INVALID_PARAMETER
Definition: CascPort.h:210
Definition: CascCommon.h:227
TCascStorage * IsValidStorageHandle(HANDLE hStorage)
Definition: CascOpenStorage.cpp:100

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool WINAPI CascOpenStorage ( const TCHAR szDataPath,
DWORD  dwLocaleMask,
HANDLE phStorage 
)
1012 {
1013  TCascStorage * hs;
1014  int nError = ERROR_SUCCESS;
1015 
1016  // Allocate the storage structure
1017  hs = (TCascStorage *)CASC_ALLOC(TCascStorage, 1);
1018  if(hs == NULL)
1019  nError = ERROR_NOT_ENOUGH_MEMORY;
1020 
1021  // Load the storage configuration
1022  if(nError == ERROR_SUCCESS)
1023  {
1024  // Prepare the base storage parameters
1025  memset(hs, 0, sizeof(TCascStorage));
1026  hs->szClassName = "TCascStorage";
1027  hs->dwFileBeginDelta = 0xFFFFFFFF;
1029  hs->dwRefCount = 1;
1030  nError = InitializeCascDirectories(hs, szDataPath);
1031  }
1032 
1033  // Now we need to load the root file so we know the config files
1034  if(nError == ERROR_SUCCESS)
1035  {
1036  nError = LoadBuildInfo(hs);
1037  }
1038 
1039  // Load the index files
1040  if(nError == ERROR_SUCCESS)
1041  {
1042  nError = LoadIndexFiles(hs);
1043  }
1044 
1045  // Load the index files
1046  if(nError == ERROR_SUCCESS)
1047  {
1048  nError = LoadEncodingFile(hs);
1049  }
1050 
1051  // Initialize the dynamic array for extra files
1052  // Reserve space for 0x20 encoding entries
1053  if(nError == ERROR_SUCCESS)
1054  {
1056  }
1057 
1058  // Load the index files
1059  if(nError == ERROR_SUCCESS)
1060  {
1061  nError = LoadRootFile(hs, dwLocaleMask);
1062  }
1063 
1064  // If something failed, free the storage and return
1065  if(nError != ERROR_SUCCESS)
1066  {
1067  hs = FreeCascStorage(hs);
1068  SetLastError(nError);
1069  }
1070 
1071  *phStorage = (HANDLE)hs;
1072  return (nError == ERROR_SUCCESS);
1073 }
DWORD dwDefaultLocale
Definition: CascCommon.h:199
#define CASC_ALLOC(type, count)
Definition: CascCommon.h:302
void * HANDLE
Definition: CascPort.h:146
#define Array_Create(pArray, type, ItemCountMax)
Definition: DynamicArray.h:35
#define CASC_EXTRA_FILES
Definition: CascCommon.h:53
#define ERROR_NOT_ENOUGH_MEMORY
Definition: CascPort.h:208
static int LoadEncodingFile(TCascStorage *hs)
Definition: CascOpenStorage.cpp:765
static int InitializeCascDirectories(TCascStorage *hs, const TCHAR *szDataPath)
Definition: CascOpenStorage.cpp:224
int LoadBuildInfo(TCascStorage *hs)
Definition: CascFiles.cpp:826
arena_t NULL
Definition: jemalloc_internal.h:624
DWORD dwFileBeginDelta
Definition: CascCommon.h:198
DYNAMIC_ARRAY ExtraEntries
Definition: CascCommon.h:221
#define CASC_LOCALE_ENUS
Definition: CascLib.h:67
void SetLastError(int nError)
Definition: Common.cpp:75
Definition: CascCommon.h:186
DWORD dwRefCount
Definition: CascCommon.h:195
Definition: CascCommon.h:171
static TCascStorage * FreeCascStorage(TCascStorage *hs)
Definition: CascOpenStorage.cpp:934
const char * szClassName
Definition: CascCommon.h:188
#define CASC_LOCALE_ENGB
Definition: CascLib.h:75
static int LoadIndexFiles(TCascStorage *hs)
Definition: CascOpenStorage.cpp:638
#define ERROR_SUCCESS
Definition: CascPort.h:204
static int LoadRootFile(TCascStorage *hs, DWORD dwLocaleMask)
Definition: CascOpenStorage.cpp:856

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool WINAPI CascReadFile ( HANDLE  hFile,
void *  lpBuffer,
DWORD  dwToRead,
PDWORD  pdwRead 
)
460 {
461  PCASC_FILE_FRAME pFrame = NULL;
462  ULONGLONG StreamSize;
463  ULONGLONG FileOffset;
464  TCascFile * hf;
465  LPBYTE pbBuffer = (LPBYTE)pvBuffer;
466  DWORD dwStartPointer = 0;
467  DWORD dwFilePointer = 0;
468  DWORD dwEndPointer = 0;
469  DWORD dwFrameSize;
470  bool bReadResult;
471  int nError = ERROR_SUCCESS;
472 
473  // The buffer must be valid
474  if(pvBuffer == NULL)
475  {
477  return false;
478  }
479 
480  // Validate the file handle
481  if((hf = IsValidFileHandle(hFile)) == NULL)
482  {
484  return false;
485  }
486 
487  // If the file frames are not loaded yet, do it now
488  if(nError == ERROR_SUCCESS)
489  {
490  nError = EnsureFrameHeadersLoaded(hf);
491  }
492 
493  // If the file position is at or beyond end of file, do nothing
494  if(nError == ERROR_SUCCESS && hf->FilePointer >= hf->FileSize)
495  {
496  *pdwBytesRead = 0;
497  return ERROR_SUCCESS;
498  }
499 
500  // Find the file frame where to read from
501  if(nError == ERROR_SUCCESS)
502  {
503  // Get the frame
504  pFrame = FindFileFrame(hf, hf->FilePointer);
505  if(pFrame == NULL || pFrame->CompressedSize < 1)
506  nError = ERROR_FILE_CORRUPT;
507  }
508 
509  // Perform the read
510  if(nError == ERROR_SUCCESS)
511  {
512  // If not enough bytes in the file remaining, cut them
513  dwStartPointer = dwFilePointer = hf->FilePointer;
514  dwEndPointer = dwStartPointer + dwBytesToRead;
515  if(dwEndPointer > hf->FileSize)
516  dwEndPointer = hf->FileSize;
517 
518  // Perform block read from each file frame
519  while(dwFilePointer < dwEndPointer)
520  {
521  LPBYTE pbFrameData = NULL;
522  DWORD dwFrameStart = pFrame->FrameFileOffset;
523  DWORD dwFrameEnd = pFrame->FrameFileOffset + pFrame->FrameSize;
524 
525  // Shall we populate the cache with a new data?
526  if(dwFrameStart != hf->CacheStart || hf->CacheEnd != dwFrameEnd)
527  {
528  // Shall we reallocate the cache buffer?
529  if(pFrame->FrameSize > hf->cbFileCache)
530  {
531  if(hf->pbFileCache != NULL)
532  CASC_FREE(hf->pbFileCache);
533 
534  hf->pbFileCache = CASC_ALLOC(BYTE, pFrame->FrameSize);
535  hf->cbFileCache = pFrame->FrameSize;
536  }
537 
538  // We also need to allocate buffer for the raw data
539  pbFrameData = CASC_ALLOC(BYTE, pFrame->CompressedSize);
540  if(pbFrameData == NULL)
541  {
542  nError = ERROR_NOT_ENOUGH_MEMORY;
543  break;
544  }
545 
546  // Load the raw file data to memory
547  FileOffset = pFrame->FrameArchiveOffset;
548  bReadResult = FileStream_Read(hf->pStream, &FileOffset, pbFrameData, pFrame->CompressedSize);
549 
550  // Note: The raw file data size could be less than expected
551  // Happened in WoW build 19342 with the ROOT file. MD5 in the frame header
552  // is zeroed, which means it should not be checked
553  // Frame File: data.029
554  // Frame Offs: 0x013ED9F0 size 0x01325B32
555  // Frame End: 0x02713522
556  // File Size: 0x027134FC
557  if(bReadResult == false && GetLastError() == ERROR_HANDLE_EOF && !IsValidMD5(pFrame->md5))
558  {
559  // Get the size of the remaining file
560  FileStream_GetSize(hf->pStream, &StreamSize);
561  dwFrameSize = (DWORD)(StreamSize - FileOffset);
562 
563  // If the frame offset is before EOF and frame end is beyond EOF, correct it
564  if(FileOffset < StreamSize && dwFrameSize < pFrame->CompressedSize)
565  {
566  memset(pbFrameData + dwFrameSize, 0, (pFrame->CompressedSize - dwFrameSize));
567  bReadResult = true;
568  }
569  }
570 
571  // If the read result failed, we cannot finish reading it
572  if(bReadResult && VerifyDataBlockHash(pbFrameData, pFrame->CompressedSize, pFrame->md5))
573  {
574  // Convert the source frame to the file cache
575  nError = ProcessFileFrame(hf->pbFileCache,
576  pFrame->FrameSize,
577  pbFrameData,
578  pFrame->CompressedSize,
579  (DWORD)(pFrame - hf->pFrames));
580  if(nError == ERROR_SUCCESS)
581  {
582  // Set the start and end of the cache
583  hf->CacheStart = dwFrameStart;
584  hf->CacheEnd = dwFrameEnd;
585  }
586  }
587  else
588  {
589  nError = ERROR_FILE_CORRUPT;
590  }
591 
592  // Free the raw frame data
593  CASC_FREE(pbFrameData);
594  }
595 
596  // Copy the decompressed data
597  if(dwFrameEnd > dwEndPointer)
598  dwFrameEnd = dwEndPointer;
599  memcpy(pbBuffer, hf->pbFileCache + (dwFilePointer - dwFrameStart), (dwFrameEnd - dwFilePointer));
600  pbBuffer += (dwFrameEnd - dwFilePointer);
601 
602  // Move pointers
603  dwFilePointer = dwFrameEnd;
604  pFrame++;
605  }
606  }
607 
608  // Update the file position
609  if(nError == ERROR_SUCCESS)
610  {
611  if(pdwBytesRead != NULL)
612  *pdwBytesRead = (dwFilePointer - dwStartPointer);
613  hf->FilePointer = dwFilePointer;
614  }
615 
616  if(nError != ERROR_SUCCESS)
617  SetLastError(nError);
618  return (nError == ERROR_SUCCESS);
619 }
DWORD CacheEnd
Definition: CascCommon.h:249
DWORD FrameSize
Definition: CascCommon.h:131
#define CASC_ALLOC(type, count)
Definition: CascCommon.h:302
unsigned long long ULONGLONG
Definition: CascPort.h:144
bool IsValidMD5(LPBYTE pbMd5)
Definition: Common.cpp:484
bool FileStream_Read(TFileStream *pStream, ULONGLONG *pByteOffset, void *pvBuffer, DWORD dwBytesToRead)
Definition: FileStream.cpp:2551
#define ERROR_NOT_ENOUGH_MEMORY
Definition: CascPort.h:208
bool FileStream_GetSize(TFileStream *pStream, ULONGLONG *pFileSize)
Definition: FileStream.cpp:2595
#define ERROR_FILE_CORRUPT
Definition: CascPort.h:218
arena_t NULL
Definition: jemalloc_internal.h:624
DWORD FileSize
Definition: CascCommon.h:240
static int EnsureFrameHeadersLoaded(TCascFile *hf)
Definition: CascReadFile.cpp:202
BYTE * LPBYTE
Definition: CascPort.h:152
LPBYTE pbFileCache
Definition: CascCommon.h:246
static int ProcessFileFrame(LPBYTE pbOutBuffer, DWORD cbOutBuffer, LPBYTE pbInBuffer, DWORD cbInBuffer, DWORD dwFrameIndex)
Definition: CascReadFile.cpp:268
#define CASC_FREE(ptr)
Definition: CascCommon.h:303
#define ERROR_INVALID_HANDLE
Definition: CascPort.h:207
bool VerifyDataBlockHash(void *pvDataBlock, DWORD cbDataBlock, LPBYTE expected_md5)
Definition: Common.cpp:494
void SetLastError(int nError)
Definition: Common.cpp:75
PCASC_FILE_FRAME pFrames
Definition: CascCommon.h:243
DWORD cbFileCache
Definition: CascCommon.h:247
BYTE md5[MD5_HASH_SIZE]
Definition: CascCommon.h:132
unsigned int DWORD
Definition: CascPort.h:139
int GetLastError()
Definition: Common.cpp:70
DWORD CacheStart
Definition: CascCommon.h:248
static PCASC_FILE_FRAME FindFileFrame(TCascFile *hf, DWORD FilePointer)
Definition: CascReadFile.cpp:244
DWORD FrameArchiveOffset
Definition: CascCommon.h:128
TCascFile * IsValidFileHandle(HANDLE hFile)
Definition: CascOpenFile.cpp:18
Definition: CascCommon.h:126
DWORD FrameFileOffset
Definition: CascCommon.h:129
#define ERROR_INVALID_PARAMETER
Definition: CascPort.h:210
#define ERROR_HANDLE_EOF
Definition: CascPort.h:216
unsigned char BYTE
Definition: CascPort.h:136
Definition: CascCommon.h:227
DWORD FilePointer
Definition: CascCommon.h:233
TFileStream * pStream
Definition: CascCommon.h:230
#define ERROR_SUCCESS
Definition: CascPort.h:204
DWORD CompressedSize
Definition: CascCommon.h:130

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

DWORD WINAPI CascSetFilePointer ( HANDLE  hFile,
LONG  lFilePos,
LONG plFilePosHigh,
DWORD  dwMoveMethod 
)
396 {
397  TCascFile * hf;
398  ULONGLONG FilePosition;
399  ULONGLONG MoveOffset;
400  DWORD dwFilePosHi;
401 
402  // If the hFile is not a valid file handle, return an error.
403  hf = IsValidFileHandle(hFile);
404  if(hf == NULL)
405  {
407  return CASC_INVALID_POS;
408  }
409 
410  // Get the relative point where to move from
411  switch(dwMoveMethod)
412  {
413  case FILE_BEGIN:
414  FilePosition = 0;
415  break;
416 
417  case FILE_CURRENT:
418  FilePosition = hf->FilePointer;
419  break;
420 
421  case FILE_END:
422  FilePosition = hf->FileSize;
423  break;
424 
425  default:
427  return CASC_INVALID_POS;
428  }
429 
430  // Now get the move offset. Note that both values form
431  // a signed 64-bit value (a file pointer can be moved backwards)
432  if(plFilePosHigh != NULL)
433  dwFilePosHi = *plFilePosHigh;
434  else
435  dwFilePosHi = (lFilePos & 0x80000000) ? 0xFFFFFFFF : 0;
436  MoveOffset = MAKE_OFFSET64(dwFilePosHi, lFilePos);
437 
438  // Now calculate the new file pointer
439  // Do not allow the file pointer to overflow
440  FilePosition = ((FilePosition + MoveOffset) >= FilePosition) ? (FilePosition + MoveOffset) : 0;
441 
442  // CASC files can't be bigger than 4 GB.
443  // We don't allow to go past 4 GB
444  if(FilePosition >> 32)
445  {
447  return CASC_INVALID_POS;
448  }
449 
450  // Change the file position
451  hf->FilePointer = (DWORD)FilePosition;
452 
453  // Return the new file position
454  if(plFilePosHigh != NULL)
455  *plFilePosHigh = 0;
456  return hf->FilePointer;
457 }
unsigned long long ULONGLONG
Definition: CascPort.h:144
#define FILE_END
Definition: CascPort.h:167
arena_t NULL
Definition: jemalloc_internal.h:624
DWORD FileSize
Definition: CascCommon.h:240
#define CASC_INVALID_POS
Definition: CascLib.h:119
#define ERROR_INVALID_HANDLE
Definition: CascPort.h:207
void SetLastError(int nError)
Definition: Common.cpp:75
#define FILE_BEGIN
Definition: CascPort.h:165
unsigned int DWORD
Definition: CascPort.h:139
TCascFile * IsValidFileHandle(HANDLE hFile)
Definition: CascOpenFile.cpp:18
#define ERROR_INVALID_PARAMETER
Definition: CascPort.h:210
Definition: CascCommon.h:227
DWORD FilePointer
Definition: CascCommon.h:233
#define MAKE_OFFSET64(hi, lo)
Definition: Common.h:18
#define FILE_CURRENT
Definition: CascPort.h:166

+ Here is the call graph for this function:

int GetLastError ( )
71 {
72  return nLastError;
73 }
static int nLastError
Definition: Common.cpp:68

+ Here is the caller graph for this function:

void qsort_pointer_array ( void **  base,
size_t  num,
int(*)(const void *, const void *, const void *)  compare,
const void *  context 
)
534 {
535  size_t lo, hi; /* ends of sub-array currently sorting */
536  size_t mid; /* points to middle of subarray */
537  size_t loguy, higuy; /* traveling pointers for partition step */
538  size_t size; /* size of the sub-array */
539  size_t lostk[STKSIZ], histk[STKSIZ];
540  void * temp;
541  int stkptr; /* stack for saving sub-array to be processed */
542 
543  /* validation section */
544  assert(base != NULL);
545  assert(compare != NULL);
546 
547  if (num < 2)
548  return; /* nothing to do */
549 
550  stkptr = 0; /* initialize stack */
551 
552  lo = 0;
553  hi = (num-1); /* initialize limits */
554 
555  /* this entry point is for pseudo-recursion calling: setting
556  lo and hi and jumping to here is like recursion, but stkptr is
557  preserved, locals aren't, so we preserve stuff on the stack */
558 recurse:
559 
560  size = (hi - lo) + 1; /* number of el's to sort */
561 
562  /* First we pick a partitioning element. The efficiency of the
563  algorithm demands that we find one that is approximately the median
564  of the values, but also that we select one fast. We choose the
565  median of the first, middle, and last elements, to avoid bad
566  performance in the face of already sorted data, or data that is made
567  up of multiple sorted runs appended together. Testing shows that a
568  median-of-three algorithm provides better performance than simply
569  picking the middle element for the latter case. */
570 
571  mid = lo + (size / 2); /* find middle element */
572 
573  /* Sort the first, middle, last elements into order */
574  if (compare(context, base[lo], base[mid]) > 0) {
575  SWAP_ENTRIES(lo, mid);
576  }
577  if (compare(context, base[lo], base[hi]) > 0) {
578  SWAP_ENTRIES(lo, hi);
579  }
580  if (compare(context, base[mid], base[hi]) > 0) {
581  SWAP_ENTRIES(mid, hi);
582  }
583 
584  /* We now wish to partition the array into three pieces, one consisting
585  of elements <= partition element, one of elements equal to the
586  partition element, and one of elements > than it. This is done
587  below; comments indicate conditions established at every step. */
588 
589  loguy = lo;
590  higuy = hi;
591 
592  /* Note that higuy decreases and loguy increases on every iteration,
593  so loop must terminate. */
594  for (;;) {
595  /* lo <= loguy < hi, lo < higuy <= hi,
596  A[i] <= A[mid] for lo <= i <= loguy,
597  A[i] > A[mid] for higuy <= i < hi,
598  A[hi] >= A[mid] */
599 
600  /* The doubled loop is to avoid calling comp(mid,mid), since some
601  existing comparison funcs don't work when passed the same
602  value for both pointers. */
603 
604  if (mid > loguy) {
605  do {
606  loguy ++;
607  } while (loguy < mid && compare(context, base[loguy], base[mid]) <= 0);
608  }
609  if (mid <= loguy) {
610  do {
611  loguy ++;
612  } while (loguy <= hi && compare(context, base[loguy], base[mid]) <= 0);
613  }
614 
615  /* lo < loguy <= hi+1, A[i] <= A[mid] for lo <= i < loguy,
616  either loguy > hi or A[loguy] > A[mid] */
617 
618  do {
619  higuy --;
620  } while (higuy > mid && compare(context, base[higuy], base[mid]) > 0);
621 
622  /* lo <= higuy < hi, A[i] > A[mid] for higuy < i < hi,
623  either higuy == lo or A[higuy] <= A[mid] */
624 
625  if (higuy < loguy)
626  break;
627 
628  /* if loguy > hi or higuy == lo, then we would have exited, so
629  A[loguy] > A[mid], A[higuy] <= A[mid],
630  loguy <= hi, higuy > lo */
631 
632  SWAP_ENTRIES(loguy, higuy);
633 
634  /* If the partition element was moved, follow it. Only need
635  to check for mid == higuy, since before the swap,
636  A[loguy] > A[mid] implies loguy != mid. */
637 
638  if (mid == higuy)
639  mid = loguy;
640 
641  /* A[loguy] <= A[mid], A[higuy] > A[mid]; so condition at top
642  of loop is re-established */
643  }
644 
645  /* A[i] <= A[mid] for lo <= i < loguy,
646  A[i] > A[mid] for higuy < i < hi,
647  A[hi] >= A[mid]
648  higuy < loguy
649  implying:
650  higuy == loguy-1
651  or higuy == hi - 1, loguy == hi + 1, A[hi] == A[mid] */
652 
653  /* Find adjacent elements equal to the partition element. The
654  doubled loop is to avoid calling comp(mid,mid), since some
655  existing comparison funcs don't work when passed the same value
656  for both pointers. */
657 
658  higuy ++;
659  if (mid < higuy) {
660  do {
661  higuy --;
662  } while (higuy > mid && compare(context, base[higuy], base[mid]) == 0);
663  }
664  if (mid >= higuy) {
665  do {
666  higuy --;
667  } while (higuy > lo && compare(context, base[higuy], base[mid]) == 0);
668  }
669 
670  /* OK, now we have the following:
671  higuy < loguy
672  lo <= higuy <= hi
673  A[i] <= A[mid] for lo <= i <= higuy
674  A[i] == A[mid] for higuy < i < loguy
675  A[i] > A[mid] for loguy <= i < hi
676  A[hi] >= A[mid] */
677 
678  /* We've finished the partition, now we want to sort the subarrays
679  [lo, higuy] and [loguy, hi].
680  We do the smaller one first to minimize stack usage.
681  We only sort arrays of length 2 or more.*/
682 
683  if ( higuy - lo >= hi - loguy ) {
684  if (lo < higuy) {
685  lostk[stkptr] = lo;
686  histk[stkptr] = higuy;
687  ++stkptr;
688  } /* save big recursion for later */
689 
690  if (loguy < hi) {
691  lo = loguy;
692  goto recurse; /* do small recursion */
693  }
694  }
695  else {
696  if (loguy < hi) {
697  lostk[stkptr] = loguy;
698  histk[stkptr] = hi;
699  ++stkptr; /* save big recursion for later */
700  }
701 
702  if (lo < higuy) {
703  hi = higuy;
704  goto recurse; /* do small recursion */
705  }
706  }
707 
708  /* We have sorted the array, except for any pending sorts on the stack.
709  Check if there are any, and do them. */
710 
711  --stkptr;
712  if (stkptr >= 0) {
713  lo = lostk[stkptr];
714  hi = histk[stkptr];
715  goto recurse; /* pop subarray from stack */
716  }
717  else
718  return; /* all subarrays done */
719 }
#define STKSIZ
Definition: Common.cpp:524
arena_t NULL
Definition: jemalloc_internal.h:624
#define SWAP_ENTRIES(index1, index2)
Definition: Common.cpp:526
void SetLastError ( int  nError)
76 {
77  nLastError = nError;
78 }
static int nLastError
Definition: Common.cpp:68

+ Here is the caller graph for this function: