Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
this program is supposed to write to shared memory using win32 API. it is a program given as it is in text book but when i try to execute it it fails. it crashes as i click on execute
the program is supposed to write a string to shared memory
#include<windows.h>
#include<stdio.h>
int main(int argc, char *argv[])
{
HANDLE hFile, hMapFile;
LPVOID lpMapAddress;
//mapping of memory
hFile=CreateFile("temp.txt",GENERIC_WRITE,0,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL, NULL);
hMapFile = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0,0, TEXT("SharedObject"));
lpMapAddress = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
//writing into shared memory
sprintf((char*)lpMapAddress,"shared memory writing");
UnmapViewOfFile(lpMapAddress);
CloseHandle(hFile);
CloseHandle(hMapFile);
}
the reason it is crashing is because the file must be created with GENERIC_READ and GENERIC_WRITE access rights since in the CreateFileMapping() function your code specifies PAGE_READWRITE as its third argument(flProtect). This is from MSDN documentation of CreateFileMapping:
The file must be opened with access rights that are compatible with
the protection flags that the flProtect parameter specifies
PAGE_READWRITE=>Gives read/write access to a specific region of pages.
The file that hFile specifies must be created with the GENERIC_READ
and GENERIC_WRITE access rights.
so change
hFile=CreateFile("temp.txt",GENERIC_WRITE,0,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL, NULL);
to
hFile=CreateFile("temp.txt",GENERIC_WRITE | GENERIC_READ,0,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL, NULL);
One more thing you can not map a file with a size of zero. Here is from MSDN documentation of CreateFileMapping() function:
If this parameter(dwMaximumSizeLow) and dwMaximumSizeHigh are 0 (zero), the maximum size
of the file mapping object is equal to the current size of the file
that hFile identifies.
An attempt to map a file with a length of 0 (zero) fails with an error
code of ERROR_FILE_INVALID. Applications should test for files with a
length of 0 (zero) and reject those files.
If an application specifies a size for the file mapping object that is
larger than the size of the actual named file on disk, the file on
disk is increased to match the specified size of the file mapping
object.
so in your case since the file you are trying to map has initially a size of 0, the CreateFileMapping() function will fail unless you specify the size of a file mapping object in the dwMaximumSizeLow/dwMaximumSizeHigh parameters of CreateFileMapping(). You could do something like this...
HANDLE hFile, hMapFile;
LPVOID lpMapAddress;
//mapping of memory
hFile=CreateFile(L"temp.txt",GENERIC_WRITE | GENERIC_READ,0,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile!=INVALID_HANDLE_VALUE)
{
char* str="shared data to be written";//the data you want to write to the file
int strLen=::strlen(str);//get the string length of the data you want to write
hMapFile = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0,strLen, TEXT("SharedObject")); //here you also specify the size of the mapping object to be equal to the size of data you want to write
if (hMapFile != NULL && hMapFile != INVALID_HANDLE_VALUE)
{
lpMapAddress = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
//writing into shared memory
if(lpMapAddress!=NULL)
sprintf((char*)lpMapAddress,"%s","shared file write");
else
printf("error");//error message MapViewOfFile() failed
UnmapViewOfFile(lpMapAddress);
CloseHandle(hMapFile);
}
else
printf("error");//error message CreateFileMapping() failed
CloseHandle(hFile);
}
else
printf("error");//error message CreateFile() failed
Related
I am trying to find ways to manage system storage efficiently.
One thing I've noticed while using MS OneDrive is that whenever I click "Free up space" on its context menu, it converts the "Storage on disk" to 0 bytes while its File size remains the same. I want to mimic what is happening over there.
Then I researched to see if I can partially modify its attribute (allocation size) through SetFileInformationByHandle using FileAllocationInfo as its parameter. It succeeded but both of its file size and allocation size became 0.
Test code as follows:
WCHAR wcsDebug[2048];
// testfile is 1224 bytes
HANDLE hFile = CreateFile(_TEXT("C:\\test\\testfile.txt"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
FILE_ALLOCATION_INFO allocInfo;
ZeroMemory(&allocInfo, sizeof(FILE_ALLOCATION_INFO));
BOOL fResult = SetFileInformationByHandle(hFile,
FileAllocationInfo,
&allocInfo,
sizeof(FILE_ALLOCATION_INFO));
// after the execution, the size becomes 0
if (fResult)
{
swprintf_s(wcsDebug, _countof(wcsDebug), L"SetFileInfomationByHandle() Success.");
OutputDebugString(wcsDebug);
}
else
{
swprintf_s(wcsDebug, _countof(wcsDebug), L"SetFileInfomationByHandle() Failed. Err(%08X)", GetLastError());
OutputDebugString(wcsDebug);
}
}
Any more ideas on developing the thoughts?
This question already has answers here:
Crash when calling ReadFile after LockFileEx
(2 answers)
Closed 5 years ago.
So i'm trying to Read a file into a file buffer by using ReadFile, but every time it throws this exception
I don't understand why it has an access violation for writing, the file does exist, and I can see the file handle, buffer and file size in the Visual Studio autos watch
int main()
{
LPCSTR Dll = "C:\\Test.dll";
HANDLE hFile = CreateFileA(Dll, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL); // Open the DLL
DWORD FileSize = GetFileSize(hFile, NULL);
PVOID FileBuffer = VirtualAlloc(NULL, FileSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
// Read the file
ReadFile(hFile, FileBuffer, FileSize, NULL, NULL);
return 0;
}
The documentation says about the last two parameters:
lpNumberOfBytesRead [out, optional]
A pointer to the variable that receives the number of bytes read when using a synchronous hFile parameter. ReadFile sets this value to zero before doing any work or error checking. Use NULL for this parameter if this is an asynchronous operation to avoid potentially erroneous results.
This parameter can be NULL only when the lpOverlapped parameter is not NULL.
So you should call it with a pointer to a valid target to write to, instead of NULL:
DWORD outSize = 0;
ReadFile(hFile, FileBuffer, FileSize, &outSize, NULL);
Here's what I'm trying to achieve; I'm hooking onto the HttpSendRequest function (on Xbox it's XHttp) and trying dump the certificate that's in pcszHeaders which has the size of 0x1F0E.
Now the problem; it only seems to write 4 bytes, I've even tried allocating extra memory and setting each bit to 0 to see if it's the size of Headers and it continues to only write 4 bytes. I've been able to dump pcszHeaders remotely because I got the address whilst debugging but I need to dump it at run-time.
Something I notice whilst debugging - The address of pcszHeaders only shows in locals until it reaches;
printf("XHttpSendRequest: %s\n", "Creating Certificate.bin...");
Once it reaches the printf() above the address changes to 0x00000000 (bad ptr) but it still writes the first byte of correct data of pcszHeaders correctly but nothing more.
Here is the entire hook;
BOOL XHTTP_SEND_REQUEST_HOOK(
HINTERNET hRequest,
const CHAR *pcszHeaders,
DWORD dwHeadersLength,
const VOID *lpOptional,
DWORD dwOptionalLength,
DWORD dwTotalLength,
DWORD_PTR dwContext)
{
if(pcszHeaders != XHTTP_NO_ADDITIONAL_HEADERS)
{
printf("XHttpSendRequest: %s\n", "Creating Certificate.bin...");
// Setup expansion
doMountPath("Hdd:", "\\Device\\Harddisk0\\Partition1");
//create our file
HANDLE fileHandle = CreateFile("Hdd:\\Certificate.bin", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
//does file exist?
if(GetLastError()!=ERROR_ALREADY_EXISTS
||fileHandle!=INVALID_HANDLE_VALUE)
{
printf("XHttpSendRequest: %s\n", "Writing to file...");
DWORD wfbr;
//write to our file
if(WriteFile(fileHandle, pcszHeaders, 0x2000, &wfbr, NULL))
{
printf("XHttpSendRequest: %s\n", "File written!");
printf("%s\n", "Request has ended.");
CloseHandle(fileHandle);
return XHttpSendRequest(hRequest, pcszHeaders, dwHeadersLength, lpOptional, dwOptionalLength, dwTotalLength, dwContext);
}
}
}
}
EDIT: I've changed the code slightly and I've copied pcszHeaders data into another section of memory that I've created and my pointers seems to have all the correct data and I've tried Writing it to file and it still only writes 4 bytes. I've even used sizeof() instead of hard-coded 0x2000.
pcszHeaders is a char* pointer. sizeof(pcszHeaders) is 4 in a 32bit app (8 in a 64bit app). You need to use the dwHeadersLength parameter instead, which tells you how many characters are in pcszHeaders.
Also, your GetLastError() check after CreateFile() is wrong. If CreateFile() fails for any reason other than ERROR_ALREADY_EXISTS, you are entering the code block and thus writing data to an invalid file handle. When using CREATE_NEW, CreateFile() returns INVALID_HANDLE_VALUE if the file already exists. You don't need to check GetLastError() for that, checking for INVALID_HANDLE_VALUE by itself is enough. If you want to overwrite the existing file, use CREATE_ALWAYS instead.
You are also leaking the file handle if WriteFile() fails.
And you are calling the original HttpSendRequest() only if you successfully write headers to your file. If there are no headers, or the create/write fails, you are not allowing the request to proceed. Is that what you really want?
Try this instead:
BOOL XHTTP_SEND_REQUEST_HOOK(
HINTERNET hRequest,
const CHAR *pcszHeaders,
DWORD dwHeadersLength,
const VOID *lpOptional,
DWORD dwOptionalLength,
DWORD dwTotalLength,
DWORD_PTR dwContext)
{
if (pcszHeaders != XHTTP_NO_ADDITIONAL_HEADERS)
{
printf("XHttpSendRequest: Creating Certificate.bin...\n");
// Setup expansion
doMountPath("Hdd:", "\\Device\\Harddisk0\\Partition1");
//create our file
HANDLE fileHandle = CreateFile("Hdd:\\Certificate.bin", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
//is file open?
if (fileHandle != INVALID_HANDLE_VALUE)
{
printf("XHttpSendRequest: Writing to file...\n");
DWORD wfbr;
//write to our file
if (WriteFile(fileHandle, pcszHeaders, dwHeadersLength, &wfbr, NULL))
printf("XHttpSendRequest: File written!\n");
else
printf("XHttpSendRequest: Error writing to file: %u\n", GetLastError());
CloseHandle(fileHandle);
}
else
printf("XHttpSendRequest: Error creating file: %u\n", GetLastError());
}
printf("Request has ended.\n");
return XHttpSendRequest(hRequest, pcszHeaders, dwHeadersLength, lpOptional, dwOptionalLength, dwTotalLength, dwContext);
}
Finally the problem has been solved!
First I created an empty array for the data to be stored.
CHAR xtoken[0x2000];
memset(xtoken, 0, 0x2000);
The first part of the hook is to store the header data.
DWORD bufferLength = dwHeadersLength;
memcpy(xtoken, pcszHeaders, bufferLength);
I then write the data to file
WriteFile(fileHandle, (void*)&xtoken, bufferLength, &wfbr, NULL))
Success! I guess the problem was that parameter 2 of WriteFile() was incorrect.
Why can't a single thread open the same file tqize using CreateFile and an exclusive file lock to the process? The example below will fail on the second attempt to open the file by the same thread with a ERROR_SHARING_VIOLATION exception:
ERROR_SHARING_VIOLATION 32 (0x20) The process cannot access the file
because it is being used by another process.
Emphasis on the word "process" above; it is the same process (and even the same thread) that tries to open the same file twize.
#include <Windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hOutputFile1 = CreateFile(
// File name
L"test.dat",
// Requested access to the file
GENERIC_READ | GENERIC_WRITE,
// Share mode. 0 equals exclusive lock for the process
0,
// Pointer to a security attribute structure
NULL,
// Action to take on file
OPEN_ALWAYS,
// File attributes and flags
FILE_ATTRIBUTE_NORMAL,
// Template file
NULL
);
if (hOutputFile1 == INVALID_HANDLE_VALUE)
{
// Error
DWORD lastError = GetLastError();
return (int)lastError;
}
// opening the same file for the second time will return a ERROR_SHARING_VIOLATION exception
HANDLE hOutputFile2 = CreateFile(
// File name
L"test.dat",
// Requested access to the file
GENERIC_READ | GENERIC_WRITE,
// Share mode. 0 equals exclusive lock by the process
0,
// Pointer to a security attribute structure
NULL,
// Action to take on file
OPEN_ALWAYS,
// File attributes and flags
FILE_ATTRIBUTE_NORMAL,
// Template file
NULL
);
if (hOutputFile2 == INVALID_HANDLE_VALUE)
{
// Error
DWORD lastError = GetLastError();
return (int)lastError;
}
return 0;
}
The error message text is a bit misleading, but the fact that the two calls to CreateFile are made from the same thread in the same process doesn't change anything. Once the first call to CreateFile has been made, then subsequent calls to CreateFile, irrespective of where they originate, must obey the sharing rules.
I guess the error message text tries to capture the most common source of a sharing violation. Namely two processes competing for the same file. But the simple fact is that once you have opened a file with exclusive sharing, then no other attempts to open the file can succeed.
That old message is misleading. It doesn't matter what process or thread is opening a file. File sharing is handle-based.
From MSDN:
dwShareMode [in]:
If this parameter is zero and CreateFile succeeds, the file or device
cannot be shared and cannot be opened again until the handle to the
file or device is closed.
This is just talking about opening the file or device and the error message is something general and confusing.
Instead of trying to re-open the file, you should hold the handle and do your job.
I created a named pipe using WCF and C#, and a client to connect to it so that I know that it is working correctly. Now I'm trying to create a c++ client. So far I have been able to get the name of the pipe, connect to it, and write some data to it. When I try to read from it I'm getting error code 998 Invalid access to memory location. Here is the code I'm using:
HANDLE hPipe = CreateFile(pipeName.c_str(), GENERIC_WRITE | GENERIC_READ, 2, NULL, OPEN_EXISTING, NULL, NULL);
BOOL bWrite = WriteFile(hPipe, &message, size, &bytesWritten, NULL);
LPVOID buffer = 0;
DWORD bytesRead;
BOOL bRead = ReadFile(hPipe, buffer, 10, &bytesRead, NULL);
I'm not sure what I'm doing wrong.
No memory has been allocated for buffer, it is currently a null pointer, and the code is requesting that 10 bytes of data be read into an array that does not exist. From ReadFile():
lpBuffer [out]
A pointer to the buffer that receives the data read from a file or device.
To rectify:
char buffer[10];