summaryrefslogtreecommitdiff
path: root/src/ToolBox/superpmi/superpmi/filecache.cpp
blob: 0455fa9fe7a6f462770a16e35224044db771ee3c (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
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

// TODO-Cleanup: this class is unused

#include "standardpch.h"
#include "filecache.h"

#define FileCacheSize 0xFFFFFF // needs to be bigger than the biggest read request.

HANDLE       FileCache::cachedHandle;
bool         FileCache::openAsCache;
BYTE*        FileCache::rawBuff;
unsigned int FileCache::offset;
unsigned int FileCache::length;
__int64      FileCache::fileoffset;

HANDLE
FileCache::CreateFileA(_In_ LPCSTR lpFileName,
                       _In_ DWORD dwDesiredAccess,
                       _In_ DWORD dwShareMode,
                       _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
                       _In_ DWORD dwCreationDisposition,
                       _In_ DWORD dwFlagsAndAttributes,
                       _In_opt_ HANDLE hTemplateFile)
{
    openAsCache = false;
    rawBuff     = nullptr;
    offset      = 0;
    length      = 0;

    if ((dwShareMode & CACHE_THIS_FILE) == CACHE_THIS_FILE)
    {
        dwShareMode ^= CACHE_THIS_FILE;
        openAsCache = true;
    }
    HANDLE temp = ::CreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition,
                                dwFlagsAndAttributes, hTemplateFile);
    if (openAsCache)
        cachedHandle = temp; // yes yes.. this is unsafe.. but one accessor now is okay. bswhack
    return temp;
}

HANDLE
FileCache::CreateFileW(_In_ LPCWSTR lpFileName,
                       _In_ DWORD dwDesiredAccess,
                       _In_ DWORD dwShareMode,
                       _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
                       _In_ DWORD dwCreationDisposition,
                       _In_ DWORD dwFlagsAndAttributes,
                       _In_opt_ HANDLE hTemplateFile)
{
    openAsCache = false;
    rawBuff     = nullptr;
    offset      = 0;
    length      = 0;
    return ::CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition,
                         dwFlagsAndAttributes, hTemplateFile);
}

// Somewhat sloppy quick copy... we don't treat lpNumberOfBytesRead etc correctly
BOOL FileCache::ReadFile(_In_ HANDLE hFile,
                         _Out_writes_bytes_to_opt_(nNumberOfBytesToRead, *lpNumberOfBytesRead) __out_data_source(FILE)
                             LPVOID lpBuffer,
                         _In_ DWORD nNumberOfBytesToRead,
                         _Out_opt_ LPDWORD lpNumberOfBytesRead,
                         _Inout_opt_ LPOVERLAPPED lpOverlapped)
{
    if (!openAsCache)
        return ::ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
    else
    {
        if (rawBuff == nullptr)
        {
            rawBuff = new BYTE[FileCacheSize];
            length  = FileCacheSize;
            offset  = FileCacheSize;
        }
        if (nNumberOfBytesToRead > FileCacheSize)
        {
            printf("ERROR: nNumberOfBytesToRead exceeds FileCacheSize %u > %u\n", nNumberOfBytesToRead, FileCacheSize);
            __debugbreak();
        }
        if ((offset + nNumberOfBytesToRead) > length)
        {
            memmove(rawBuff, &rawBuff[offset],
                    length - offset); // Use memmove since we have overlapping regions more than half the time
            ::ReadFile(hFile, &rawBuff[length - offset], offset, lpNumberOfBytesRead, lpOverlapped);
            if (*lpNumberOfBytesRead == 0)
                __debugbreak();
            length -= offset - (*lpNumberOfBytesRead);
            LARGE_INTEGER DataTemp;
            LARGE_INTEGER zero;
            zero.QuadPart = 0;
            ::SetFilePointerEx(hFile, zero, &DataTemp, FILE_CURRENT);
            fileoffset = DataTemp.QuadPart;

            offset = 0;
        }
        memcpy(lpBuffer, &rawBuff[offset], nNumberOfBytesToRead);
        offset += nNumberOfBytesToRead;
        if (offset > FileCacheSize)
            __debugbreak();
        return true;
    }
}

BOOL FileCache::WriteFile(_In_ HANDLE                                         hFile,
                          _In_reads_bytes_opt_(nNumberOfBytesToWrite) LPCVOID lpBuffer,
                          _In_ DWORD nNumberOfBytesToWrite,
                          _Out_opt_ LPDWORD lpNumberOfBytesWritten,
                          _Inout_opt_ LPOVERLAPPED lpOverlapped)
{
    if (!openAsCache)
        return ::WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);
    else
    {
        printf("ERROR: We only support one file open via the cache.\n");
        __debugbreak();
        return false;
    }
}

BOOL FileCache::CloseHandle(_In_ HANDLE hObject)
{
    if (!openAsCache)
        return ::CloseHandle(hObject);
    else
    {
        if (rawBuff != nullptr)
            delete[] rawBuff;
        return ::CloseHandle(hObject);
    }
}
__int64 FileCache::GetFilePos(HANDLE hFile)
{
    return (fileoffset - (__int64)length) + (__int64)offset;
}