188 lines
6.0 KiB
C++
188 lines
6.0 KiB
C++
/*****************************************************************************/
|
|
/* CascOpenFile.cpp Copyright (c) Ladislav Zezula 2014 */
|
|
/*---------------------------------------------------------------------------*/
|
|
/* System-dependent directory functions for CascLib */
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Date Ver Who Comment */
|
|
/* -------- ---- --- ------- */
|
|
/* 01.05.14 1.00 Lad The first version of CascOpenFile.cpp */
|
|
/*****************************************************************************/
|
|
|
|
#define __CASCLIB_SELF__
|
|
#include "CascLib.h"
|
|
#include "CascCommon.h"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Local functions
|
|
|
|
PCASC_CKEY_ENTRY FindCKeyEntry_CKey(TCascStorage * hs, LPBYTE pbCKey, PDWORD PtrIndex)
|
|
{
|
|
return (PCASC_CKEY_ENTRY)hs->CKeyMap.FindObject(pbCKey, PtrIndex);
|
|
}
|
|
|
|
PCASC_CKEY_ENTRY FindCKeyEntry_EKey(TCascStorage * hs, LPBYTE pbEKey, PDWORD PtrIndex)
|
|
{
|
|
return (PCASC_CKEY_ENTRY)hs->EKeyMap.FindObject(pbEKey, PtrIndex);
|
|
}
|
|
|
|
bool OpenFileByCKeyEntry(TCascStorage * hs, PCASC_CKEY_ENTRY pCKeyEntry, DWORD dwOpenFlags, HANDLE * PtrFileHandle)
|
|
{
|
|
TCascFile * hf = NULL;
|
|
int nError = ERROR_FILE_NOT_FOUND;
|
|
|
|
// If the CKey entry is NULL, we consider the file non-existant
|
|
if(pCKeyEntry != NULL)
|
|
{
|
|
// Create the file handle structure
|
|
if((hf = new TCascFile(hs, pCKeyEntry)) != NULL)
|
|
{
|
|
hf->bVerifyIntegrity = (dwOpenFlags & CASC_STRICT_DATA_CHECK) ? true : false;
|
|
hf->bDownloadFileIf = (hs->dwFeatures & CASC_FEATURE_ONLINE) ? true : false;
|
|
hf->bOvercomeEncrypted = (dwOpenFlags & CASC_OVERCOME_ENCRYPTED) ? true : false;
|
|
nError = ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
nError = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
}
|
|
|
|
// Give the output parameter, no matter what
|
|
PtrFileHandle[0] = (HANDLE)hf;
|
|
|
|
// Handle last error
|
|
if(nError != ERROR_SUCCESS)
|
|
SetLastError(nError);
|
|
return (nError == ERROR_SUCCESS);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Public functions
|
|
|
|
bool WINAPI CascOpenFile(HANDLE hStorage, const void * pvFileName, DWORD dwLocaleFlags, DWORD dwOpenFlags, HANDLE * PtrFileHandle)
|
|
{
|
|
PCASC_CKEY_ENTRY pCKeyEntry = NULL;
|
|
TCascStorage * hs;
|
|
const char * szFileName;
|
|
DWORD FileDataId = CASC_INVALID_ID;
|
|
BYTE CKeyEKeyBuffer[MD5_HASH_SIZE];
|
|
int nError = ERROR_SUCCESS;
|
|
|
|
// This parameter is not used
|
|
CASCLIB_UNUSED(dwLocaleFlags);
|
|
|
|
// Validate the storage handle
|
|
hs = TCascStorage::IsValid(hStorage);
|
|
if(hs == NULL)
|
|
{
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return false;
|
|
}
|
|
|
|
// Validate the other parameters
|
|
if(PtrFileHandle == NULL)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return false;
|
|
}
|
|
|
|
// Retrieve the CKey/EKey from the file name in different modes
|
|
switch(dwOpenFlags & CASC_OPEN_TYPE_MASK)
|
|
{
|
|
case CASC_OPEN_BY_NAME:
|
|
|
|
// The 'pvFileName' must be zero terminated ANSI file name
|
|
szFileName = (const char *)pvFileName;
|
|
if(szFileName == NULL || szFileName[0] == 0)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return false;
|
|
}
|
|
|
|
// The first chance: Try to find the file by name (using the root handler)
|
|
pCKeyEntry = hs->pRootHandler->GetFile(hs, szFileName);
|
|
if(pCKeyEntry != NULL)
|
|
break;
|
|
|
|
// Second chance: If the file name is actually a file data id, we convert it to file data ID
|
|
if(IsFileDataIdName(szFileName, FileDataId))
|
|
{
|
|
pCKeyEntry = hs->pRootHandler->GetFile(hs, FileDataId);
|
|
if(pCKeyEntry != NULL)
|
|
break;
|
|
}
|
|
|
|
// Third chance: If the file name is a string representation of CKey/EKey, we try to query for CKey
|
|
if(IsFileCKeyEKeyName(szFileName, CKeyEKeyBuffer))
|
|
{
|
|
pCKeyEntry = FindCKeyEntry_CKey(hs, CKeyEKeyBuffer);
|
|
if(pCKeyEntry != NULL)
|
|
break;
|
|
|
|
pCKeyEntry = FindCKeyEntry_EKey(hs, CKeyEKeyBuffer);
|
|
if(pCKeyEntry != NULL)
|
|
break;
|
|
}
|
|
|
|
SetLastError(ERROR_FILE_NOT_FOUND);
|
|
return false;
|
|
|
|
case CASC_OPEN_BY_CKEY:
|
|
|
|
// The 'pvFileName' must be a pointer to 16-byte CKey or EKey
|
|
if(pvFileName == NULL)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return false;
|
|
}
|
|
|
|
// Search the CKey map in order to find the CKey entry
|
|
pCKeyEntry = FindCKeyEntry_CKey(hs, (LPBYTE)pvFileName);
|
|
break;
|
|
|
|
case CASC_OPEN_BY_EKEY:
|
|
|
|
// The 'pvFileName' must be a pointer to 16-byte CKey or EKey
|
|
if(pvFileName == NULL)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return false;
|
|
}
|
|
|
|
// Search the CKey map in order to find the CKey entry
|
|
pCKeyEntry = FindCKeyEntry_EKey(hs, (LPBYTE)pvFileName);
|
|
break;
|
|
|
|
case CASC_OPEN_BY_FILEID:
|
|
|
|
// Retrieve the file CKey/EKey
|
|
pCKeyEntry = hs->pRootHandler->GetFile(hs, CASC_FILE_DATA_ID_FROM_STRING(pvFileName));
|
|
break;
|
|
|
|
default:
|
|
|
|
// Unknown open mode
|
|
nError = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
// Perform the open operation
|
|
return OpenFileByCKeyEntry(hs, pCKeyEntry, dwOpenFlags, PtrFileHandle);
|
|
}
|
|
|
|
bool WINAPI CascCloseFile(HANDLE hFile)
|
|
{
|
|
TCascFile * hf;
|
|
|
|
hf = TCascFile::IsValid(hFile);
|
|
if (hf != NULL)
|
|
{
|
|
delete hf;
|
|
return true;
|
|
}
|
|
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return false;
|
|
}
|
|
|