You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

143 lines
4.1 KiB

#include <cstdio>
#include <set>
#include <string>
#include <iterator>
#include <vector>
#include <algorithm>
#include <fstream>
#include <memory>
#include "devilution.h"
#include "stubs.h"
namespace dvl {
struct memfile {
std::string path;
std::vector<char> buf;
std::size_t pos = 0;
};
static std::set<memfile*> files;
HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
{
char name[DVL_MAX_PATH];
TranslateFileName(name, sizeof(name), lpFileName);
DUMMY_PRINT("file: %s (%s)", lpFileName, name);
UNIMPLEMENTED_UNLESS(dwDesiredAccess == (DVL_GENERIC_READ | DVL_GENERIC_WRITE));
memfile* file = new memfile;
file->path = name;
if (dwCreationDisposition == DVL_OPEN_EXISTING) {
// read contents of existing file into buffer
std::ifstream filestream(file->path, std::ios::binary);
if(!filestream.fail()) {
file->buf.insert(file->buf.begin(),
std::istreambuf_iterator<char>(filestream),
std::istreambuf_iterator<char>());
}
} else if (dwCreationDisposition == DVL_CREATE_ALWAYS) {
// start with empty file
} else {
UNIMPLEMENTED();
}
files.insert(file);
return file;
}
WINBOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped)
{
memfile* file = static_cast<memfile*>(hFile);
UNIMPLEMENTED_UNLESS(!lpOverlapped);
size_t len = std::min<size_t>(file->buf.size() - file->pos, nNumberOfBytesToRead);
std::copy(file->buf.begin() + file->pos, file->buf.begin() + file->pos + len, static_cast<char*>(lpBuffer));
file->pos += len;
*lpNumberOfBytesRead = len;
return true;
}
DWORD GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
{
memfile* file = static_cast<memfile*>(hFile);
return file->buf.size();
}
WINBOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)
{
memfile* file = static_cast<memfile*>(hFile);
UNIMPLEMENTED_UNLESS(!lpOverlapped);
if(!nNumberOfBytesToWrite)
return true;
if(file->buf.size() < file->pos + nNumberOfBytesToWrite)
file->buf.resize(file->pos + nNumberOfBytesToWrite);
std::copy(static_cast<const char*>(lpBuffer),
static_cast<const char*>(lpBuffer) + nNumberOfBytesToWrite,
file->buf.begin() + file->pos);
file->pos += nNumberOfBytesToWrite;
*lpNumberOfBytesWritten = nNumberOfBytesToWrite;
return true;
}
DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod)
{
memfile* file = static_cast<memfile*>(hFile);
UNIMPLEMENTED_UNLESS(!lpDistanceToMoveHigh);
if (dwMoveMethod == DVL_FILE_BEGIN) {
file->pos = lDistanceToMove;
} else if (dwMoveMethod == DVL_FILE_CURRENT) {
file->pos += lDistanceToMove;
} else {
UNIMPLEMENTED();
}
if(file->buf.size() < file->pos + 1)
file->buf.resize(file->pos + 1);
return file->pos;
}
WINBOOL SetEndOfFile(HANDLE hFile)
{
memfile* file = static_cast<memfile*>(hFile);
file->buf.erase(file->buf.begin() + file->pos, file->buf.end());
return true;
}
DWORD GetFileAttributesA(LPCSTR lpFileName)
{
char name[DVL_MAX_PATH];
TranslateFileName(name, sizeof(name), lpFileName);
std::ifstream filestream(name, std::ios::binary);
if (filestream.fail()) {
SetLastError(DVL_ERROR_FILE_NOT_FOUND);
return (DWORD)-1;
}
return 0x80;
}
WINBOOL SetFileAttributesA(LPCSTR lpFileName, DWORD dwFileAttributes)
{
return true;
}
WINBOOL CloseHandle(HANDLE hObject)
{
memfile* file = static_cast<memfile*>(hObject);
if (files.find(file) == files.end())
return true;
std::unique_ptr<memfile> ufile(file); // ensure that delete file is
// called on returning
std::ofstream filestream(file->path + ".tmp", std::ios::binary);
if (filestream.fail())
return false;
filestream.write(file->buf.data(), file->buf.size());
if(filestream.fail())
return false;
if(std::rename((file->path + ".tmp").c_str(), file->path.c_str()))
return false;
return true;
}
} // namespace dvl