aboutsummaryrefslogtreecommitdiff
path: root/dep/CascLib/src/CascCommon.cpp
blob: f5e346ec14ca3f89ef004ed8ed721c1c80d24b75 (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
/*****************************************************************************/
/* CascCommon.cpp                         Copyright (c) Ladislav Zezula 2014 */
/*---------------------------------------------------------------------------*/
/* Common functions for CascLib                                              */
/*---------------------------------------------------------------------------*/
/*   Date    Ver   Who  Comment                                              */
/* --------  ----  ---  -------                                              */
/* 29.04.14  1.00  Lad  The first version of CascCommon.cpp                  */
/*****************************************************************************/

#define __CASCLIB_SELF__
#include "CascLib.h"
#include "CascCommon.h"

//-----------------------------------------------------------------------------
// Functions

LPBYTE LoadInternalFileToMemory(TCascStorage * hs, PCASC_CKEY_ENTRY pCKeyEntry, DWORD * pcbFileData)
{
    LPBYTE pbFileData = NULL;
    HANDLE hFile = NULL;
    DWORD cbFileData = pcbFileData[0];
    DWORD dwBytesRead = 0;
    int nError = ERROR_SUCCESS;

    // Open the file either by CKey or by EKey
    if(OpenFileByCKeyEntry(hs, pCKeyEntry, CASC_STRICT_DATA_CHECK, &hFile))
    {
        // Retrieve the size of the file. Note that the caller might specify
        // the real size of the file, in case the file size is not retrievable
        // or if the size is wrong. Example: ENCODING file has size specified in BUILD
        if(cbFileData == 0 || cbFileData == CASC_INVALID_SIZE)
        {
            cbFileData = CascGetFileSize(hFile, NULL);
            if(cbFileData == 0 || cbFileData == CASC_INVALID_SIZE)
                nError = ERROR_FILE_CORRUPT;
        }

        // Retrieve the size of the ENCODING file
        if(nError == ERROR_SUCCESS)
        {
            // Allocate space for the ENCODING file
            pbFileData = CASC_ALLOC(BYTE, cbFileData);
            if(pbFileData != NULL)
            {
                // Read the entire file to memory
                CascReadFile(hFile, pbFileData, cbFileData, &dwBytesRead);
                if(dwBytesRead != cbFileData)
                {
                    nError = ERROR_FILE_CORRUPT;
                }
            }
            else
            {
                nError = ERROR_NOT_ENOUGH_MEMORY;
            }
        }

        // Close the file
        CascCloseFile(hFile);
    }
    else
    {
        nError = GetLastError();
    }

    // Handle errors
    if(nError != ERROR_SUCCESS)
    {
        // Free the file data
        CASC_FREE(pbFileData);
        cbFileData = 0;

        // Set the last error
        SetLastError(nError);
    }

    // Give the loaded file length
    if(pcbFileData != NULL)
        *pcbFileData = cbFileData;
    return pbFileData;
}

LPBYTE LoadFileToMemory(const TCHAR * szFileName, DWORD * pcbFileData)
{
    TFileStream * pStream;
    ULONGLONG FileSize = 0;
    LPBYTE pbFileData = NULL;
    DWORD cbFileData = 0;

    // Open the stream for read-only access and read the file
    // Note that this fails when the game is running (sharing violation).
    pStream = FileStream_OpenFile(szFileName, STREAM_FLAG_READ_ONLY | STREAM_PROVIDER_FLAT | BASE_PROVIDER_FILE);
    if(pStream != NULL)
    {
        // Retrieve the file size
        FileStream_GetSize(pStream, &FileSize);
        cbFileData = (DWORD)FileSize;

        // Do not load zero files or too larget files
        if(0 < FileSize && FileSize <= 0x2000000)
        {
            // Allocate file data buffer. Make it 1 byte longer
            // so string functions can put '\0' there
            pbFileData = CASC_ALLOC(BYTE, cbFileData + 1);
            if(pbFileData != NULL)
            {
                if(!FileStream_Read(pStream, NULL, pbFileData, cbFileData))
                {
                    CASC_FREE(pbFileData);
                    cbFileData = 0;
                }
            }
            else
            {
                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
                cbFileData = 0;
            }
        }
        else
        {
            SetLastError(ERROR_BAD_FORMAT);
            cbFileData = 0;
            assert(false);
        }

        // Close the file stream
        FileStream_Close(pStream);
    }

    // Give out values
    if(pcbFileData != NULL)
        pcbFileData[0] = cbFileData;
    return pbFileData;
}

void FreeCascBlob(PQUERY_KEY pBlob)
{
    if(pBlob != NULL)
    {
        CASC_FREE(pBlob->pbData);
        pBlob->cbData = 0;
    }
}