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);
Related
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);
}
I have a very small FAT16 partition in a .bin file.
I have mapped it into memory using: CreateFile, CreateFileMapping and MapViewOfFile.
What I want to do is to read a specific byte of the file.
For example I want to read offset from 0x36 to 0x3A to check if this is a FAT16 partition:
This is my code until:
#include <Windows.h>
#include <stdio.h>
void CheckError (BOOL condition, LPCSTR message, UINT retcode);
int main(int argc, char *argv[])
{
HANDLE hFile;
HANDLE hMap;
char *pView;
DWORD TamArchivoLow, TamArchivoHigh;
//> open file
hFile =CreateFile (L"disk10mb.bin", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
CheckError(hFile == INVALID_HANDLE_VALUE,"ERROR opening the file", 1);
//> get file size.
TamArchivoLow = GetFileSize (hFile, &TamArchivoHigh);
//> Create the map
hMap = CreateFileMapping (hFile, NULL, PAGE_READWRITE, TamArchivoHigh, TamArchivoLow, NULL);
CheckError(NULL== hMap, "ERROR executing CreateFileMapping", 1);
//> Create the view
pView= (char *) MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, TamArchivoLow);
CheckError(NULL==pView, "ERROR executing MapViewOfFile", 1);
// Access the file through pView
//////////////////////////////////////
//////////////////////////////////////
//>Free view and map
UnmapViewOfFile(pView);
CloseHandle(hMap);
CloseHandle(hFile);
return 0;
}
void CheckError (BOOL condition, LPCSTR message, UINT retcode)
{
if (condition)
{
printf ("%s\n", message);
ExitProcess (retcode);
}
}
pview[0x36] will give you the byte at offset 0x36, and so on. To check for the FAT16 signature you could, for instance:
if (pview[0x36] == 'F' && pview[0x37] == 'A' && pview[0x38] == 'T' &&
pview[0x39] == '1' && pview[0x3A] == '6') {
// ...
}
I am a student so I apologize up front for not using the correct forum protocols. I am new to C, and really new to Win32 API. My assignment is to write a small C program that copies the contents of an existing file to a new file, using only Win32 I/O system calls: CreateFile(), ReadFile(), WriteFile(), etc... File names are to be specified on the command line. Right now I'm just trying to get the basics functions in place, I will then focus on error handling. This code compiles, creates a new file, but the data does not get copied to it. Any advice? thanks for taking a look!
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int main(int argc, char *argv[])
{
char buff[4096];
DWORD dwBytesRead, dwBytesWritten;
DWORD dwBytesToWrite = (DWORD)strlen(buff);
//open source file and read it
HANDLE source;
// Create a handle for the source file
source=CreateFile(argv[1], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
// Check for errors
if ( source == INVALID_HANDLE_VALUE ){
printf("Error, source file not opened.");
exit(EXIT_FAILURE);
}
else printf("The source file is %s\n", argv[1]);
//create a new file
HANDLE target;
target = CreateFile(argv[2], GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if ( target == INVALID_HANDLE_VALUE ){
printf("Error, target file not created.");
exit(EXIT_FAILURE);
}
else printf("The source file is %s\n", argv[2]);
//copy contents
ReadFile(source, buff, 4096, &dwBytesRead, NULL);
WriteFile(target, buff, dwBytesToWrite, &dwBytesWritten, NULL);
//copy complete
CloseHandle(source);
CloseHandle(target);
return 0;
}
As mentioned in comments, your code has a few mistakes in it. Try something more like this instead:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int main(int argc, char *argv[])
{
char buff[4096];
DWORD dwBytesRead, dwBytesWritten;
// Open the source file
HANDLE source = CreateFileA(argv[1], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
// Check for error
if (source == INVALID_HANDLE_VALUE) {
printf("Source file not opened. Error %u", GetLastError());
return EXIT_FAILURE;
}
printf("The source file is %s\n", argv[1]);
// Create a new file
HANDLE target = CreateFileA(argv[2], GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
// Check for error
if (target == INVALID_HANDLE_VALUE) {
printf("Target file not created. Error %u", GetLastError());
CloseHandle(source);
return EXIT_FAILURE;
}
printf("The target file is %s\n", argv[2]);
// Copy contents
bool ok = true;
do {
// Read file, check for error
if (!ReadFile(source, buff, sizeof(buff), &dwBytesRead, NULL)) {
printf("Source file not read from. Error %u", GetLastError());
ok = false;
break;
}
// Check for EOF reached
if (dwBytesRead == 0) {
break;
}
// Write file, check for error
if (!WriteFile(target, buff, dwBytesRead, &dwBytesWritten, NULL)) {
printf("Target file not written to. Error %u", GetLastError());
ok = false;
break;
}
}
while (true);
// Copy complete
CloseHandle(source);
CloseHandle(target);
// Check for error
if (!ok) {
DeleteFileA(argv[2]);
return EXIT_FAILURE;
}
// all OK
return 0;
}
I can't send chunks of data bigger than 420 bytes. For example if i try to send 421 bytes, i can't read it with ReadFile. If I check the maislot info with GetMailslotInfo( handleRead, 0, &msgSize, 0, 0 ); then msgSize will always be -1.
So this will never work for me:
err = WriteFile( handleWrite, wcharArrayToSend, 421, &numBytesWritten, NULL );
Does anyone know a reason for this behavior? Is this a normal behavior?
Per MSDN's documentation on mailslots:
The data in a mailslot message can be in any form, but cannot be larger than 424 bytes when sent between computers.
To send messages that are larger than 424 bytes between computers, use named pipes or Windows Sockets instead.
I'm not sure what you've done wrong, but mailslots can definitely handle messages greater than 421 bytes. Here's some test code (that runs successfully):
Server:
#include <windows.h>
#include <stdio.h>
int main() {
HANDLE mailslot = CreateMailslot("\\\\.\\mailslot\\myslot",
0,
MAILSLOT_WAIT_FOREVER,
NULL);
if (mailslot == INVALID_HANDLE_VALUE) {
fprintf(stderr, "Unable to create mailslot.");
return 1;
}
char buffer[2048];
OVERLAPPED ovlp = {0};
ovlp.hEvent = CreateEvent(NULL, false, false, NULL);
if (ovlp.hEvent == NULL) {
fprintf(stderr, "Unable to create Event.");
return 2;
}
DWORD read;
do {
ReadFile(mailslot, buffer, sizeof(buffer), &read, &ovlp);
buffer[read] = 0;
WaitForSingleObject(ovlp.hEvent, INFINITE);
printf("%s\n", buffer);
} while (strcmp(buffer, "exit"));
return 0;
}
Client:
#include <windows.h>
#include <stdio.h>
int main() {
HANDLE mailslot = CreateFile("\\\\.\\mailslot\\myslot",
GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
0,
NULL);
if (INVALID_HANDLE_VALUE == mailslot) {
fprintf(stderr, "Unable to open mailslot.\n");
return 1;
}
char buffer[2048];
DWORD written;
for (int i=0; i<1024; i++)
buffer[i] = 'A' + (i%26);
buffer[1023] = '\0';
size_t len = strlen(buffer);
WriteFile(mailslot, buffer, len, &written, NULL);
WriteFile(mailslot, "exit", 4, &written, NULL);
return 0;
}
Result:
E:\C\source>mailslot
ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZAB
CDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCD
EFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF
GHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGH
IJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJ
KLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKL
MNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMN
OPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOP
QRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQR
STUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRST
UVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUV
WXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWX
YZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHI
exit
It's quite a simple C code to read a file text, I've done this other times but don't know why now the ReadFile function keeps returning FALSE meaning it fails.
Obviously the text file input.txt exists and the CreateFile function succeeds (or at least doen't return INVALID_HANDLE_VALUE
#include <stdio.h>
#include <windows.h>
int main(int argc, char *argv[])
{
char ReadBuffer[256] = {0};
HANDLE hFile1;
int n = 0;
DWORD bytesread = 5;
printf("Press enter to read the file 'input.txt' ... ");
getch();
if ( (hFile1 = CreateFile(TEXT("input.txt"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL) == INVALID_HANDLE_VALUE))
{
printf("INVALID_HANDLE_VALUE");
return -1;
}
if ( ReadFile(hFile1, ReadBuffer, bytesread, &bytesread, NULL) == FALSE )
{
printf("ReadFile ERROR");
CloseHandle(hFile1);
return -2;
}
printf("\n\nRead bytes: %d \n\n", bytesread);
CloseHandle(hFile1);
return 0;
}
The error is a simple misplacement of a parenthesis.
if ( (hFile1 = CreateFile(TEXT("input.txt"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)