Memory Mapped File changes not reflected in underlying file - c

I am learning MMF in win32 C.
I can't seem to see what I am missing...
Here is my code:
#include "stdafx.h"
#include <Windows.h>
int main()
{
wchar_t szfilename[] = L"c:\\temp\\mmf.txt";
HANDLE hFile = CreateFile(
szfilename,
GENERIC_READ | GENERIC_WRITE, //dwDesiredAccess
FILE_SHARE_READ | FILE_SHARE_WRITE, //dwShareMode
NULL, //lpSecurityAttributes
CREATE_NEW, //dwCreationDisposition
FILE_ATTRIBUTE_NORMAL, //dwFlagsAndAttributes
NULL); //hTemplateFile
if (hFile == INVALID_HANDLE_VALUE)
{
DWORD error = GetLastError();
if (error != ERROR_FILE_EXISTS)
exit(-1);
}
//Now create the file mapping
HANDLE hMap = CreateFileMapping(
hFile,
NULL, //LPSECURITY_ATTRIBUTES lpAttributes,
PAGE_READWRITE, //DWORD flProtect,
0, //DWORD dwMaximumSizeHigh,
1024, //DWORD dwMaximumSizeLow,
L"myMappingFile"); //LPCTSTR lpName
if (hMap == (HANDLE)ERROR_ALREADY_EXISTS || hMap == NULL)
{
DWORD error = GetLastError();
exit(-2);
}
LPCTSTR pBuf = (LPTSTR)MapViewOfFile(hMap, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
0);
if (pBuf == NULL)
{
printf("Could not map view of file (%d).\n",
GetLastError());
return -2;
}
wchar_t szMsg[] = L"Msg from first process";
CopyMemory((PVOID)pBuf, szMsg, wcslen(szMsg) * sizeof(wchar_t));
UnmapViewOfFile(pBuf);
CloseHandle(hMap);
CloseHandle(hFile);
return 0;
}
I open a file, associate it with a memory mapping and create a view. Then I write data (copy) into the buffer (view) and close things down.
I am trying to figure out why my underlying file (c:\temp\mmf.txt) does not contain the msg after the routine executes. Am I missing something? The file size remains 0.

Here is a snippet of code that demonstrates memory mapping a file. In the end I think you will just benefit from reading the MSDN docs for each API call you are using a little more carefully.
HANDLE hFile = INVALID_HANDLE_VALUE;
HANDLE hFileMapping = NULL;
LPVOID pBase = NULL;
__try
{
hFile = CreateFile(filename,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if(hFile == INVALID_HANDLE_VALUE) __leave;
hFileMapping = CreateFileMapping(hFile,
NULL,
PAGE_READONLY,
0, 0, NULL);
if(hFileMapping == NULL) __leave;
pFileBase = MapViewOfFile(hFileMapping,
FILE_MAP_READ,
0, 0, 0);
if(pBase == NULL) __leave;
}
__finally
{
if(hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
if(hFileMapping != NULL) CloseHandle(hFileMapping);
}

Related

GetFileAttributesW causes Access violation reading location x (GetLastError returns 8)

I am currently trying to implement a program that loads multiple files into memory, for further processing. To see if the file exists I made a function that uses GetFileAttributesW to check if the file indeed exists.
The first file gets loaded correctly, but once I try to load the second file, I get the access violation (GetLastError returns 8; ERROR_NOT_ENOUGH_MEMORY). I can safely rule out that I don't have enough RAM, as the files are max. 500kb in size and I am never loading more than 20 (I have 16GB of RAM).
I also have rights to access he file, etc.
inline BOOL FileExists(const TCHAR* szPath)
{
DWORD dwAttrib = GetFileAttributesW(szPath); // ERROR here (1st iteration everything is fine)
return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
.
.
.
FILE_DATA LoadFileIntoMemory(const TCHAR* FileName)
{
PTCHAR FinalPath = VirtualAlloc(NULL, MAX_PATH, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
PTCHAR FilePath = L"C:\\Users\\invasi0nZ\\"; //
concat(FinalPath, FilePath, MAX_PATH);
concat(FinalPath, FileName, MAX_PATH);
if (!FileExists(FinalPath))
{
memset(FinalPath, 0, MAX_PATH);
FilePath = L"C:\\Users\\invasi0nZ\\Documents\\";
concat(FinalPath, FilePath, MAX_PATH);
concat(FinalPath, FileName, MAX_PATH);
}
HANDLE File = CreateFileW(FinalPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (File == INVALID_HANDLE_VALUE)
{
return (FILE_DATA){ NULL, NULL };
}
int FileSize = GetFileSize(File, NULL);
PBYTE RawFile = VirtualAlloc(NULL, FileSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
DWORD dwRead;
size_t FileSize = GetFileSize(File, NULL);
ReadFile(File, RawFile, FileSize, &dwRead, NULL);
CloseHandle(File);
VirtualFree(FinalPath, sizeof(FinalPath), MEM_FREE);
return (FILE_DATA) { RawFile, FileSize };
}
.
.
.
void LoadAllFiles(Array FileNames)
{
for (int i = 0; i < FileNames.used; i++)
{
FILE_DATA file_data = LoadFileIntoMemory(FileNames.array[i].file_name);
// Store file_data, etc.
}
// Do stuff with files here
}
As far as I see I am closing all required handles and freeing everything that I can without breaking the program.
Thank you very much in advance!
You are not allocating enough memory with VirtualAlloc(), thus your concat() function can cause a buffer overflow. Since you are compiling with UNICODE enabled, TCHAR is wchar_t, which is 2 bytes in size. You need to take that size into account when allocating memory for FinalPath, as well as when clearing FinalPath with memset().
Change this:
PTCHAR FinalPath = VirtualAlloc(NULL, MAX_PATH, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
...
memset(FinalPath, 0, MAX_PATH);
To this:
PTCHAR FinalPath = VirtualAlloc(NULL, sizeof(TCHAR) * MAX_PATH, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
...
memset(FinalPath, 0, sizeof(TCHAR) * MAX_PATH);
There are other problems with your code, too. You are not checking if VirtualAlloc() is successful before using the returned pointer. You are leaking the allocated memory if CreateFileW() fails. And you are declaring FileSize twice.
Try this instead:
FILE_DATA LoadFileIntoMemory(const TCHAR* FileName)
{
PTCHAR FinalPath = VirtualAlloc(NULL, sizeof(TCHAR) * MAX_PATH, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!FinalPath)
return (FILE_DATA){ NULL, 0 };
PTCHAR FilePath = TEXT("C:\\Users\\invasi0nZ\\"); //
concat(FinalPath, FilePath, MAX_PATH);
concat(FinalPath, FileName, MAX_PATH);
if (!FileExists(FinalPath))
{
memset(FinalPath, 0, sizeof(TCHAR) * MAX_PATH);
FilePath = TEXT("C:\\Users\\invasi0nZ\\Documents\\");
concat(FinalPath, FilePath, MAX_PATH);
concat(FinalPath, FileName, MAX_PATH);
}
HANDLE File = CreateFile(FinalPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (File == INVALID_HANDLE_VALUE)
{
VirtualFree(FinalPath, 0, MEM_RELEASE);
return (FILE_DATA){ NULL, 0 };
}
VirtualFree(FinalPath, 0, MEM_RELEASE);
DWORD FileSize = GetFileSize(File, NULL);
if (FileSize == INVALID_FILE_SIZE)
{
CloseHandle(File);
return (FILE_DATA){ NULL, 0 };
}
PBYTE RawFile = VirtualAlloc(NULL, FileSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!RawFile)
{
CloseHandle(File);
return (FILE_DATA){ NULL, 0 };
}
DWORD dwRead;
if (!ReadFile(File, RawFile, FileSize, &dwRead, NULL))
{
VirtualFree(RawFile, 0, MEM_RELEASE);
RawFile = NULL;
dwRead = 0;
}
CloseHandle(File);
return (FILE_DATA) { RawFile, dwRead };
}
That being said, you don't really need FileExists() at all, as CreateFile() can tell you whether the file exists or not, thus avoiding a race condition in your code if another process creates/deletes the file after you check for its existence but before you open it.
You should also get rid of VirtualAlloc() for FinalPath, you don't need to allocate that string dynamically. Just declare the array statically instead.
And the Win32 API has functions for concatenating path segments together, so you don't need to write your own. It also has functions for querying the paths of the user's profile and Documents folders, you should not hard-code those paths.
Try something more like this instead:
#include <windows.h>
#include <pathcch.h>
#include <shlobj.h>
HANDLE OpenFileInFolder(CSIDL FolderID, const TCHAR *FileName)
{
TCHAR FilePath[MAX_PATH];
HRESULT Res = SHGetFolderPath(NULL, FolderID, NULL, SHGFP_TYPE_CURRENT, FilePath);
if (Res != S_OK)
{
SetLastError(Res);
return INVALID_HANDLE_VALUE;
}
Res = PathCchCombine(FilePath, MAX_PATH, FilePath, FileName);
if (Res != S_OK)
{
SetLastError(Res);
return INVALID_HANDLE_VALUE;
}
return CreateFile(FilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
}
FILE_DATA LoadFileIntoMemory(const TCHAR* FileName)
{
HANDLE File = OpenFileInFolder(CSIDL_PROFILE, FileName);
if ((File == INVALID_HANDLE_VALUE) && (GetLastError() == ERROR_FILE_NOT_FOUND))
File = OpenFileInFolder(CSIDL_MYDOCUMENTS, FileName);
if (File == INVALID_HANDLE_VALUE)
return (FILE_DATA){ NULL, 0 };
DWORD FileSize = GetFileSize(File, NULL);
if (FileSize == INVALID_FILE_SIZE)
{
CloseHandle(File);
return (FILE_DATA){ NULL, 0 };
}
PBYTE RawFile = VirtualAlloc(NULL, FileSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!RawFile)
{
CloseHandle(File);
return (FILE_DATA){ NULL, 0 };
}
DWORD dwRead;
if (!ReadFile(File, RawFile, FileSize, &dwRead, NULL))
{
VirtualFree(RawFile, 0, MEM_RELEASE);
RawFile = NULL;
dwRead = 0;
}
CloseHandle(File);
return (FILE_DATA) { RawFile, dwRead };
}

How to use deviceiocontrol function properly

This is my code:
Code:
HANDLE HandelUsb= CreateFile(L"\\\\.\\G:", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (HandelUsb == INVALID_HANDLE_VALUE)
{
printf("Terminal failure: Unable to open usb ERROR CODE:0x%x\n", GetLastError());
return 1;
}
DISK_GEOMETRY d = { 0 };
DWORD dwReturned = 0;
int gs =DeviceIoControl(HandelUsb, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &d, sizeof(DISK_GEOMETRY),&dwReturned, NULL);
printf("%d\n", gs);
if (d.MediaType == RemovableMedia)
{
DWORD dwReturned2 = 0;
MEDIA_SERIAL_NUMBER_DATA data={ 0 };
if (DeviceIoControl(HandelUsb, IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER, NULL, 0, &data,sizeof(MEDIA_SERIAL_NUMBER_DATA), &dwReturned2, NULL)) {
printf("SerialNumberLength %d\nResult %d\nReserved[2] %s\nSerialNumberData[1] %s ", data.SerialNumberLength, data.Result, data.Reserved, data.SerialNumberData);
}
else {
printf("faild to get serial number ERROR CODE:0x%x\n", GetLastError());
}
}
CloseHandle(HandelUsb);
return 0;
Everything works well except for the function
Code:
DeviceIoControl(HandelUsb, IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER, NULL, 0, &data,sizeof(MEDIA_SERIAL_NUMBER_DATA), &dwReturned2, NULL)
It always fails (returns a value of 0), GetLastError returns the value 0X1 (problem function).
Maybe someone here can show me what I'm missing here?
Following the comment of #IInspectable ,i changed the code to it:
//volume handle to device handle
VOLUME_DISK_EXTENTS volumeToDevice = { 0 };
DWORD Returned = 0;
DeviceIoControl(HandelToUsb,IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,NULL,0,&volumeToDevice,sizeof(VOLUME_DISK_EXTENTS),&Returned,NULL);
WCHAR volume[150] ;
swprintf_s(volume, L"\\\\.\\PhysicalDrive%d", volumeToDevice.Extents[0].DiskNumber);
wprintf(L"%s\n", volume);
//handle to phisicalDrive
HANDLE HandelUsb = CreateFile(volume, 0, FILE_SHARE_READ |FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
DWORD dwReturned2 = 0;
MEDIA_SERIAL_NUMBER_DATA data={ 0 };
if (DeviceIoControl(HandelUsb, IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER, NULL, 0, &data,sizeof(MEDIA_SERIAL_NUMBER_DATA), &dwReturned2, NULL)) {
printf("SerialNumberLength %d\nResult %d\nReserved[2] %s\nSerialNumberData[1] %s ", data.SerialNumberLength, data.Result, data.Reserved, data.SerialNumberData);
}
else {
printf("faild to get serial number ERROR CODE:0x%x\n", GetLastError());
}
I still get a failure 0X1 on function
DeviceIoControl (Handel Usb, IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER, NULL, 0, & data, sizeof (MEDIA_SERIAL_NUMBER_DATA), & dwReturned2, NULL)
I ran Windus 7
i tried to Change the permissions function CreateFile (Add GENERIC_EXECUTE , replace to GENERIC_ALL add FILE_ATTRIBUTE_NORMAL ), play with the parameters of the DeviceIoControl.

CreateFileA fails with INVALID_HANDLE_VALUE error for Read Text FIle

I am trying to read a simple text file in Win32 app. But I am getting INVALID_HANDLE_VALUE error in the following code
void Avatar::readData(LPCSTR filename)
{
LPVOID data[4096] = {};
HANDLE hFile;
MessageBox(NULL, (LPCWSTR)filename, L"File", MB_OK);
hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
MessageBox(NULL, L"Failed to CreateFile - 'hFile'", L"ERROR", MB_OK);
}
DWORD fileSize = GetFileSize(hFile, &fileSize);
DWORD read = -1;
if (!ReadFile(hFile, static_cast< LPVOID >(&data), 4096, &read, NULL))
{
DWORD err = GetLastError();
MessageBox(NULL, L"Failed to ReadFile - 'hFile'", L"ERROR", MB_OK);
}
CloseHandle(hFile);
}
Can anyone help me to solve it?

GetFileTime returns an old time

I want to download a file from a server if it´s newer then the one on my disc.
I wrote following code:
bool bDownload = true;
HANDLE hFile = CreateFile(strFileLocal, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
FILETIME ftLocal = { 0 };
FILETIME ftWrite = { 0 }; // only for testing
GetFileTime(hFile, &ftLocal, NULL, &ftWrite);
FILETIME ftRemote = arrTimes[i]; //get size from server
if (ftLocal.dwLowDateTime >= ftRemote.dwLowDateTime && ftLocal.dwHighDateTime >= ftRemote.dwHighDateTime)
{
bDownload = false;
}
CloseHandle(hFile);
}
After this is done I download the file and set the filetime from server to the file:
//set file date
HANDLE hFile = CreateFile(strFileLocal, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
FILETIME ftRemote = arrTimes[i];
SetFileTime(hFile, &ftRemote, NULL, &ftRemote);
CloseHandle(hFile);
}
Now my problem:
If I replace the file on disk with a new creation time, GetFileTime will read the time I had set. But in the file explorer in windows the file has the new creation time.
For testing I tried to read last writing time. But this is the same time as creation time.
Thanks a lot.
How can I fix this problem? Do I something wrong?

Using ReadFile to read entire PhysicalDrive contents

I am fairly new to C, and I am trying to write a small application that will read the entire raw contents of a drive.
Here is my code;
int main(int argc, char *argv[]) {
HANDLE hFile;
DWORD dwBytesRead;
char buff[512];
hFile = CreateFile("\\\\.\\PhysicalDrive2", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
if(hFile == INVALID_HANDLE_VALUE){
printf("%d",GetLastError());
return;
}
SetFilePointer(hFile, 512*0, NULL, FILE_BEGIN);
ReadFile(hFile, buff, 512, &dwBytesRead, NULL);
CloseHandle(hFile);
return 0;
}
How do I put the ReadFile into a loop to read all the data on the drive? I eventually need to save the contents of the buffer to the disk.
Thanks
The loop might look like this:
hFile = CreateFile(...);
if (hFile == INVALID_HANDLE_VALUE)
{
// handle error
}
while (true)
{
unsigned char buff[32768]; // needs to be a multiple of sector size
DWORD dwBytesRead;
if (!ReadFile(hFile, buff, sizeof buff, &dwBytesRead, NULL))
{
// handle error
}
if (dwBytesRead == 0)
{
break; // we reached the end
}
// do something with the dwBytesRead that were read
}
CloseHandle(hFile);

Resources