aboutsummaryrefslogtreecommitdiff
path: root/dep/CascLib/src/CascOpenFile.cpp
blob: 741ab1e10052f45f2272c7103dcba2b388488769 (plain)
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
/*****************************************************************************/
/* 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;
            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;
}