1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
/*****************************************************************************/
/* 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;
}
|