Reading large mapped text file in C++ - c++

I am attempting to display a large amount of text(barely less than 1GB).
My code:
HANDLE hFile;
DWORD dwBytesRead = 0;
OVERLAPPED ol = {0};
HANDLE m_hMapFile;
hFile = CreateFile(_T("test.txt"),
GENERIC_WRITE | GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);
m_hMapFile = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
LPVOID m_lpMapAddress = MapViewOfFile(m_hMapFile, FILE_MAP_ALL_ACCESS, 0,
0, 0);
}
Now that the text file is mapped, how do I display its contents? I have attempted the following (poor) implementation:
char *mappedData = (char*)m_lpMapAddress;
for(int k = 0; k < strlen(mappedData); k++){
cout<<mappedData [k];
}
This is obviously not the right way to display the text contents. Is there a more efficient method?

You may try doing all your output at once:
cout.write(mappedData, mappedSize);
But note that printing a gigabyte of data to console is not likely to be efficient anyhow.
Console output has purpose of being read by user (programmatic parsing is secondary thing). Do you expect user to read 1 GB of data?

Related

How to use OVERLAPPED to write data at specific offset (win32 programming)

(I'm not native English speaker so sorry for potential mistake :p)
I want to write a Windows tool that can accelerate big files copying just like FastCopy. But get stuck at the very first step: Write data to specific offset of a file via OVERLAPPED (with WriteFile).
Here is my code:
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <Windows.h>
#include <fileapi.h>
LPOVERLAPPED SetupOvl(DWORD OffsetHigh, DWORD Offset) {
printf("Ovl??: Got Offset %d\n", Offset);
LPOVERLAPPED Ovl = (LPOVERLAPPED)malloc(sizeof(OVERLAPPED));
Ovl->Internal = 0;
Ovl->InternalHigh = 0;
Ovl->OffsetHigh = OffsetHigh;
Ovl->Offset = Offset;
Ovl->Pointer = NULL;
Ovl->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
return Ovl;
}
int main()
{
HANDLE hf,hf2;
void* buffer2 = (void*)malloc(2 << 16);
void* buffer = (void*)malloc(2 << 16);
int readed_number = 0, writed_number = 0;
DWORD written_number = 0;
DWORD wn1 = 0, wn2 = 0;
// OpenThread
DeleteFileW(L"C:\\Users\\Lev\\Downloads\\dst.txt");
hf = CreateFileW(
L"C:\\Users\\Lev\\Downloads\\src.txt",
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
hf2 = CreateFileW(
L"C:\\Users\\Lev\\Downloads\\dst.txt",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_NEW,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);
// ReadThread
BOOL ret = ReadFile(
hf,
buffer,
2 << 15,
(LPDWORD)&readed_number,
NULL
);
SetFilePointer(hf2, 16, 0, FILE_BEGIN);
SetEndOfFile(hf2);
LPOVERLAPPED Ovl1 = SetupOvl(0, 2);
WriteFile(hf2, buffer, 6, NULL, Ovl1);
LPOVERLAPPED Ovl2 = SetupOvl(0, 12);
buffer = (void*)((char*)buffer + (unsigned int)(10));
WriteFile(hf2, buffer, 4, NULL, Ovl2);
ret = GetOverlappedResult(hf2, Ovl1, &wn1, TRUE);
ret = GetOverlappedResult(hf2, Ovl2, &wn2, TRUE);
printf("Write_A: Write %d Bytes!\n", wn1);
printf("Write_B: Write %d Bytes!\n", wn2);
free(Ovl1);
free(Ovl2);
CloseHandle(hf);
CloseHandle(hf2);
return 0;
}
Output from console:
Ovl??: Got Offset 2
Ovl??: Got Offset 8
Write_A: Write 4 Bytes!
Write_B: Write 5 Bytes!
Content of src.txt: 1234567890abcdefghijklmn
Content of dst.txt: abcd56 (6 charactors and lots of 0x00)
In the code I try to write "123456" at 3rd byte and "abcd" at 13th byte. But it didn't work. I have look up MSDN and some books but found not code examples I need.
By the way, which is the best way to make a multi-thread acceleration? Multi-thread reading or multi-thread writing? Is it possible to use OVERLAPPED I/O to implement multiple threads writing to the same file in parallel? Or does it just write sequentially?
Any helpful suggestion is appreciated!

DeviceIoControl assistance

Using C++, trying to use DeviceIOControl to send mouse clicks directly through driver. Very little documentation seems to exist on this. Very annoying. This is all I figured out so far. Have no idea what goes into any parameter after dwIoControlNode. I've seen keyboard examples, but no mouse ones.
EDIT: Appreciate your help Remy, will try your suggestions tomorrow, been working on this all day and am braindead.
int i = 0;
GUID MouseyBoi;
HANDLE HIDD = NULL;
HIDD_ATTRIBUTES DeviceAttributes;
ULONG Needed, l;
HDEVINFO DeviceInfoSet;
SP_DEVICE_INTERFACE_DATA DevData;
PSP_INTERFACE_DEVICE_DETAIL_DATA DevDetail;
PSP_DEVICE_INTERFACE_DATA InfData;
DeviceInfoSet = SetupDiGetClassDevs(&GUID_DEVCLASS_MOUSE, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, &DevData, NULL, 0, &Needed, 0);
DevDetail = (SP_DEVICE_INTERFACE_DETAIL_DATA*)GlobalAlloc(GPTR, 1 + 4);
DevDetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
HIDD = CreateFile(DevDetail->DevicePath, GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, 0, NULL);
HidD_GetAttributes(HIDD, &DeviceAttributes);
std::cout << DeviceAttributes.VersionNumber << std::endl;
std::cout << DeviceAttributes.ProductID;
First off, you need to escape \ characters in a string literal, eg:
LPCWSTR FileName = L"USB\\VID_046D&PID_C07E&MI_00\\6&361cde46&0&0000";
And second, this is not a valid file/device path that you can open with CreateFile() anyway. It should look more like this:
LPCWSTR FileName = L"\\\\?\\USB#VID_046D&PID_C07E&MI_00#6&361cde46&0&0000#{<guid>}";
You can use SetupDiGetDeviceInterfaceDetail() to get a device path that CreateFile() will accept.
That being said, once you do manage to open a handle to the USB device, the DeviceIoControl() call should look like the following, since you are just inserting input data, not getting any output back out (but I could be wrong, as there is no documentation for IOCTL_MOUSE_INSERT_DATA that I can find):
MOUSE_INPUT_DATA MouseInput = {};
MouseInput.UnitId = 0;
MouseInput.ButtonFlags = MOUSE_LEFT_BUTTON_DOWN;
// set other fields as needed ...
DeviceIoControl(hFile, IOCTL_MOUSE_INSERT_DATA, &MouseInput, sizeof(MOUSE_INPUT_DATA), NULL, 0, NULL, NULL);

How to convert L"\\\\.\\C:" to L"\\\\.\\PhysicalDrive0"

I am newbie. The code is that I copied on internet. And I don't really understand it.
I'm learning C ++, so even though the code is C, I want to switch to C ++. I need to understand the code and output the screen:
Partition Styles/Scheme: is MBR disk/drive // is GPT disk/drive // or is RAW disk/drive
Partition Number of a Disk/Drive
I put breakpoint at line below, press F5 on Visual Studio 2013 (run as admin):
DWORD part_num = szPartINF.PartitionNumber;
If I leave:
hDevice = CreateFile(L"\\\\.\\C:", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
the code runs successfully (part_num have value = 2 . It is right, because my Disk0 have 2 partitions)
And, I change to:
hDevice = CreateFile(L"\\\\.\\PhysicalDrive0", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
the code runs fails/unsuccess (part_num = 0)
I need to use "\\\.\\PhysicalDrive0" rather than "\\\.\\C:".
I still have another problem: I use the clean command in DiskPart for My Hard Drive. When I ran the test, the code did not recognize PartitionStyle RAW correctly, because this time my hard drive was RAW DISK (and certainly not PartitionStyle MBR or PartitionStyle GPT).
Please help me.
Thanks.
#include "windows.h"
#include <stdio.h>
#include <iostream>
//////// ok, go ///////////
int main(int argc, char* argv[])
{
HANDLE hDevice = INVALID_HANDLE_VALUE;
PARTITION_INFORMATION_EX szPartINF;
DWORD cbReturned = 0;
__try
{
hDevice = CreateFile(L"\\\\.\\PhysicalDrive0", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
//hDevice = CreateFile(L"\\\\.\\C:", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
if (hDevice == INVALID_HANDLE_VALUE) { return FALSE; }
RtlZeroMemory(&szPartINF, sizeof(szPartINF));
if (FALSE != DeviceIoControl(hDevice, IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0, (LPVOID)&szPartINF, sizeof(PARTITION_INFORMATION_EX), &cbReturned, NULL))
{
DWORD part_num = szPartINF.PartitionNumber;
DWORD part_style = szPartINF.PartitionStyle;
return TRUE;
}
else
{
cbReturned = GetLastError();
wprintf(L"\n%08X (%d)\n", cbReturned, cbReturned);
}
}
__finally
{
if (hDevice != INVALID_HANDLE_VALUE) { CloseHandle(hDevice); }
}
return FALSE;
bool success;
cin >> success; //for wait to close cmd.
}
"\\\\.\PhysicalDrive0" is not necessarily "\\\\.\\C:".
You can check This PC->Manage->Storage->Disk Management:
The Disk 0 means PhysicalDrive0.If you need the corresponding physical disk.You can refer to How to list physical disks?

Windows C++ -- Using DeviceIoControl to return a product string

I am trying to return the "product string" for a HID using DeviceIoControl in Windows. Here is my code:
for (int i = 0; i < nDevices; i++)
{
wchar_t* productString = new wchar_t[POINTER_DEVICE_PRODUCT_STRING_MAX];
HANDLE potentialUsbDevice = CreateFile(devInfoDataBuffer[i]->DevicePath, GENERIC_READ,
NULL,
NULL,
OPEN_EXISTING,
0,
NULL);
if (potentialUsbDevice != INVALID_HANDLE_VALUE) {
DeviceIoControl(potentialUsbDevice, IOCTL_HID_GET_PRODUCT_STRING, 0, 0, productString, 0, 0, 0);
wprintf(L"%s", productString);
}
delete[] productString;
CloseHandle(potentialUsbDevice);
}
Unfortunately, I am not getting anything human-readable. Is there something wrong with my function call or is it an issue of formatting?
Thank you for your help and consideration on this topic.
You need to pass the size of the output buffer (in bytes) to DeviceIoControl. You also need to pass lpBytesReturned as non-NULL:
DWORD bytes_returned;
DeviceIoControl (potentialUsbDevice, IOCTL_HID_GET_PRODUCT_STRING, 0, 0,
productString, POINTER_DEVICE_PRODUCT_STRING_MAX * sizeof (wchar_t),
&bytes_returned, 0);
Also, check for errors (not shown in my code for brevity) and call CloseHandle inside your if statement.

How to read something to the RAW disk and then write it some further in C++?

I'd like to first write something to a disk device, then read the same data and write it some further. My code looks like this:
std::string devicePath = "\\\\.\\PhysicalDrive0"; //'0' is only example here
HANDLE source = CreateFile(disk.c_str(), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, NULL, NULL);
BOOST_TEST_REQUIRE(source, "Failed to create file handle.");
std::unique_ptr<CHAR[]> primaryBuffer(new CHAR[DEFAULT_FILESIZE]);
std::unique_ptr<CHAR[]> checkBuffer(new CHAR[DEFAULT_FILESIZE]);
for (auto i = 0; i < DEFAULT_FILESIZE; ++i) {
primaryBuffer[i] = 'x';
checkBuffer[i] = ' ';
}
WriteFile(source, primaryBuffer.get(), DEFAULT_FILESIZE, NULL, NULL);
//Here I move the pointer to write data in new place.
DWORD destination = SetFilePointer(source, DEFAULT_FILESIZE, NULL, FILE_BEGIN);
WriteFile(&destination, source, DEFAULT_FILESIZE, NULL, NULL);
ReadFile(source, primaryBuffer.get(), DEFAULT_FILESIZE, NULL, NULL);
ReadFile(&destination, checkBuffer.get(), DEFAULT_FILESIZE, NULL, NULL);
BOOST_TEST_MESSAGE(checkBuffer.get());
BOOST_TEST_MESSAGE(primaryBuffer.get());
Unfortunately, both buffers are different and I've tried almost everything to check what's wrong. Maybe somebody has any idea what I'm doing wrong?