I need to load a file from the hard drive to a virtual file in RAM. I then need to access this virtual file using the fopen function (I need to get the FILE pointer from it). Is this possible?
For now, I only loaded the file to stringstream:
std::ifstream file("File.zip", ios::in | ios::binary);
if (file.is_open())
{
//clear:
ProtectedZipBuffer.str(std::string());
ProtectedZipBuffer << file.rdbuf();
file.close();
}
What I'm trying to do is to mod an old game. I would need to load an encrypted file (that's for later, at the moment I'm just trying to see if the virtual file works), decrypt it to a virtual file and return the read-only FILE pointer to game (from my DLL file to the main game process). This is needed, because I would like to use the purchased / licensed sound files, but the End User License forces me to encrypt files in order to disallow users from accessing copyrighted audio files by exploring game files.
Could somebody please give me some ideas how to do this?
EDIT:
I've tried the FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE
method, unfortunately no matter what, it's always writing data (around 100MB) to disk (even though I have over 8GB RAM free).
Here's the code I am using:
string SourceFileStr = "TEST_FILE_SOURCE.bin";
string DestinationFileStr = "DESTINATION_FILE.bin";
wstring DestinationFileWstr = L"DESTINATION_FILE.bin";
if (FileExistsW(DestinationFileWstr.c_str())) {
DeleteFileW(DestinationFileWstr.c_str());
}
SECURITY_ATTRIBUTES sa;
SECURITY_DESCRIPTOR sd;
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
DWORD dwLastError = ::GetLastError();
//LOG4CPLUS_ERROR(m_Logger, "Cannot launch file '" << strFullFilePath << "'. Failed to initialize security descriptor. GetLastError=" << dwLastError);
//return dwLastError;
return 0;
}
if (!SetSecurityDescriptorDacl(
&sd, // A pointer to the SECURITY_DESCRIPTOR structure to which the function adds the DACL
TRUE, // presence of a DACL in the security descriptor
NULL, // allows all access to the object
FALSE // DACL has been explicitly specified by a user
))
{
DWORD dwLastError = ::GetLastError();
//LOG4CPLUS_ERROR(m_Logger, "Cannot launch file '" << strFullFilePath << "'. Failed to set security descriptor DACL. GetLastError=" << dwLastError);
//return dwLastError;
return 0;
}
if (!SetSecurityDescriptorGroup(
&sd, // A pointer to the SECURITY_DESCRIPTOR structure whose primary group is set by this function
NULL, // no primary group
FALSE // Indicates whether the primary group information was derived from a default mechanism
))
{
DWORD dwLastError = ::GetLastError();
//LOG4CPLUS_ERROR(m_Logger, "Cannot launch file '" << strFullFilePath << "'. Failed to set security descriptor primary group. GetLastError=" << dwLastError);
//return dwLastError;
return 0;
}
if (!SetSecurityDescriptorOwner(
&sd, // A pointer to the SECURITY_DESCRIPTOR structure whose owner is set by this function.
NULL, // If this parameter is NULL, the function clears the security descriptor's owner information. This marks the security descriptor as having no owner.
FALSE // Indicates whether the owner information is derived from a default mechanism.
))
{
DWORD dwLastError = ::GetLastError();
//LOG4CPLUS_ERROR(m_Logger, "Cannot launch file '" << strFullFilePath << "'. Failed to set security descriptor owner information. GetLastError=" << dwLastError);
//return dwLastError;
return 0;
}
if (!SetSecurityDescriptorSacl(
&sd, // A pointer to the SECURITY_DESCRIPTOR structure to which the function adds the SACL
FALSE, // the security descriptor does not contain a SACL
NULL, // security descriptor has a NULL SACL
FALSE // A pointer to a flag that is set to the value of the SE_SACL_DEFAULTED flag in the SECURITY_DESCRIPTOR_CONTROL structure if a SACL exists for the security descriptor
))
{
DWORD dwLastError = ::GetLastError();
//LOG4CPLUS_ERROR(m_Logger, "Cannot launch file '" << strFullFilePath << "'. Failed to set security descriptor SACL. GetLastError=" << dwLastError);
//return dwLastError;
return 0;
}
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = TRUE;
DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
//DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
// DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE;
//DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY;
hFileDecryptedWrite = ::CreateFile(DestinationFileWstr.c_str(), GENERIC_WRITE, dwShareMode, &sa, CREATE_NEW, dwFlagsAndAttributes, NULL);
//verify we created the file.
if (hFileDecryptedWrite == INVALID_HANDLE_VALUE) {
DWORD dwLastError = ::GetLastError();
//return dwLastError;
return 0;
}
std::streamsize const buffer_size = 64 * 1024;
std::ifstream file(SourceFileStr.c_str(), ios::in | ios::binary);
if (file.is_open()) {
if (file)
{
do
{
char buffer[buffer_size];
file.read(buffer, buffer_size);
size_t extracted = file.gcount();
//std::streamsize bytes_read = file.gcount();
//size_t nBytesRead = file.readsome(buffer, buffer_size);
//MessageBoxA(NULL, to_string(extracted).c_str(), "bytes read now:", MB_OK);
//result.process_bytes(buffer, ifs.gcount());
DWORD numBytesWritten;
if (!::WriteFile(hFileDecryptedWrite, buffer, extracted, &numBytesWritten, (LPOVERLAPPED)NULL)) {
DWORD dwLastError = ::GetLastError();
//LOG4CPLUS_ERROR(m_Logger, "Failed to write file to %TEMP% folder. GetLastError=" << dwLastError);
//return dwLastError;
MessageBoxA(NULL,"FAILED TO WRITE TO FILE", "ERROR", MB_OK);
return 0;
}
} while (file);
}
}
file.close();
//CloseHandle(hFileDecryptedWrite);
I am also using the CreateFileMapping / MapViewOfFile
method for some other things. Unfortunately, there's no way to get a FILE * pointer which I could pass to the game process.
The fmem
library: https://github.com/Snaipe/fmem
Seems to do exactly the same thing on Windows as creating the file with FILE_ATTRIBUTE_TEMPORARY
Is there anything else I could try?