i'm traing to do 2 process that do this:
Process A (the client) :
- It opens a temporary file for writing (use GetTempFileName to
obtain a unique file name).
- It starts Process B passing as argument the name of the file.
- It reads from standard input strings of characters, and it writes
those strings on the intermediate file.
Use string of constant length (e.g., #define MAX_LEN 100).
- It stops reading strings from standard input when it receives an
end-of-file (ctrl-Z).
- Before terminating, it writes the string
".end"
as last line of the file.
Process B (the server) works as follows:
- It opens the intermediate file for reading.
- It reads lines as soon as they are available, and it prints them
out on standard output.
Process A keeps the file open, and it always locks the next part of
the file before unlocking the previous part.
Process B runs in parallel, and it reads a shared file, waiting to
have access to single lines to read them.
but seams that the ReadFile on process B do not wait until the fileLock is removed so it terminate befor the first line is inserted
process A:
#include <windows.h>
#include <process.h>
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <io.h>
#define MAX_LEN 100
int _tmain(int argc, LPTSTR argv[]){
TCHAR tmpFileName[MAX_PATH];
TCHAR tmppath[MAX_PATH];
TCHAR moment[MAX_PATH];
TCHAR command[MAX_PATH + 256];
UINT uRetVal = 0;
HANDLE bufferW,next;
DWORD n;
PROCESS_INFORMATION piS;
STARTUPINFO siS;
TCHAR buffer[MAX_LEN];
int i=0;
OVERLAPPED ov = { 0, 0, 0, 0, NULL };
LARGE_INTEGER FilePos;
ZeroMemory(&siS, sizeof(siS));
siS.cb = sizeof(siS);
ZeroMemory(&piS, sizeof(piS));
uRetVal = GetTempFileName(_T("."), // directory for tmp files
_T(""), // temp file name prefix
0, // create unique name
tmpFileName); // buffer for name
if (uRetVal == 0)
{
_tprintf("\n errore apertura temp file");
return (3);
}
GetCurrentDirectory(MAX_PATH, moment);
//_stprintf(tmppath, "%s\\ %s",moment,tmpFileName);
_tprintf("\n CLIENT PATH %s \n",moment);
//_stprintf(command,"%s %s","C:\\Users\\zio gianni\\Documents\\Visual Studio 2013\\Projects\\lab11server\\Debug\\lab11server.exe",tmpFileName);
_stprintf(command, "%s %s", "server.exe", tmpFileName);
bufferW = CreateFile(tmpFileName, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
next = CreateFile(tmpFileName, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (next == INVALID_HANDLE_VALUE) {
_tprintf(_T("Cannot open client file. Error: %x\n"),
GetLastError());
_tprintf(" \n Nome File: %s\n", "./prova.bin");
return 2;
}
if (bufferW == INVALID_HANDLE_VALUE) {
_tprintf(_T("Cannot open client file. Error: %x\n"),
GetLastError());
_tprintf(" \n Nome File: %s\n", "./prova.bin");
return 2;
}
FilePos.QuadPart = i*MAX_LEN * sizeof (TCHAR);
ov.Offset = FilePos.LowPart;
ov.OffsetHigh = FilePos.HighPart;
ov.hEvent = 0;
LockFileEx(bufferW, LOCKFILE_EXCLUSIVE_LOCK, 0, FilePos.LowPart, FilePos.HighPart, &ov);
printf("file bloccato avvio server con comand: %s\n", command);
if (!CreateProcess(NULL, // No module name (use command line)
command, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
TRUE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&siS, // Pointer to STARTUPINFO structure
&piS) // Pointer to PROCESS_INFORMATION structure
)
{
printf("CreateProcess failed (%d).\n", GetLastError());
return -5;
}
while (TRUE){
scanf("%s",buffer);
if (strcmp(buffer, "EOF")==0){
break;
}
WriteFile(bufferW, buffer, MAX_LEN*sizeof(TCHAR), &n, NULL);
FilePos.QuadPart =(i+1)* MAX_LEN * sizeof (TCHAR);
ov.Offset = FilePos.LowPart;
ov.OffsetHigh = FilePos.HighPart;
ov.hEvent = 0;
if (i % 2 == 0){
LockFile(next, LOCKFILE_EXCLUSIVE_LOCK, 0, FilePos.LowPart, FilePos.HighPart, &ov);
FilePos.QuadPart = (i )* MAX_LEN * sizeof (TCHAR);
ov.Offset = FilePos.LowPart;
ov.OffsetHigh = FilePos.HighPart;
ov.hEvent = 0;
UnlockFile(bufferW, 0, 0, 0, &ov);
}
else{
LockFile(bufferW, LOCKFILE_EXCLUSIVE_LOCK, 0, FilePos.LowPart, FilePos.HighPart, &ov);
FilePos.QuadPart = (i )* MAX_LEN * sizeof (TCHAR);
ov.Offset = FilePos.LowPart;
ov.OffsetHigh = FilePos.HighPart;
ov.hEvent = 0;
UnlockFile(next, 0, 0, 0, &ov);
}
i++;
}
sprintf(buffer, ".end");
WriteFile(bufferW, buffer, MAX_LEN*sizeof(TCHAR), &n ,NULL);
if (i % 2 == 0){
FilePos.QuadPart = (i)* MAX_LEN * sizeof (TCHAR);
ov.Offset = FilePos.LowPart;
ov.OffsetHigh = FilePos.HighPart;
ov.hEvent = 0;
UnlockFile(bufferW, 0, FilePos.LowPart, FilePos.HighPart, &ov);
}
else{
FilePos.QuadPart = (i)* MAX_LEN * sizeof (TCHAR);
ov.Offset = FilePos.LowPart;
ov.OffsetHigh = FilePos.HighPart;
ov.hEvent = 0;
UnlockFile(next, 0, FilePos.LowPart, FilePos.HighPart, &ov);
}
// Wait until child process exits.
WaitForSingleObject(piS.hProcess, INFINITE);
// Close process and thread handles.
CloseHandle(piS.hProcess);
CloseHandle(piS.hThread);
return 0;
}
process B:
#include <windows.h>
#include <process.h>
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <io.h>
#define MAX_LEN 100
int _tmain(int argc, LPTSTR argv[]){
HANDLE read;
DWORD n;
int i = 0;
TCHAR buffer[MAX_LEN], path[MAX_LEN];
OVERLAPPED ov = { 0, 0, 0, 0, NULL };
LARGE_INTEGER FilePos;
read = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (read == INVALID_HANDLE_VALUE) {
_tprintf(_T("Cannot open input file. Error: %x\n"),
GetLastError());
_tprintf(" \n Nome File: %s\n", argv[1]);
return 2;
}
_tprintf(" \n Nome File APERTO: %s\n", argv[1]);
GetCurrentDirectory(MAX_LEN,path);
_tprintf(" \n path server: %s\n%s\n", path,argv[1]);
while (ReadFile(read, buffer, MAX_LEN*sizeof(TCHAR), &n, &ov) && n>0 ){
if (n == 0){
fprintf(stderr,"error readfle\n");
return -5;
}
if (strncmp(buffer, ".end", 4) == 0){
_tprintf(" \n STAMPA SERVER: esco\n");
break;
}
_tprintf(" \n STAMPA SERVER: %s\n", buffer);
}
if (n == 0){
fprintf(stderr, "error readfle\n");
return -5;
}
_tprintf("\n END SERVER");
return 0;
}
Do not use actual files for inter process communication. Use named pipes!
Search for CreateNamedPipe, there are plenty of examples.
Related
I wrote this code to encrypt a file in python with AES and now I send this file over HTTP to a client in C++ using Windows OS. And I want to decrypt this file on the C++ client, but I haven't found any libraries/usefull code to help me with this manner.
Here is the code for python:
def derive_key_and_iv(password, salt, key_length, iv_length):
d = d_i = b''
while len(d) < key_length + iv_length:
d_i = md5(d_i + str.encode(password) + salt).digest()
d += d_i
return d[:key_length], d[key_length:key_length + iv_length]
def encrypt(in_file, out_file, password, key_length=32):
bs = AES.block_size # 16 bytes
salt = urandom(bs)
key, iv = derive_key_and_iv(password, salt, key_length, bs)
cipher = AES.new(key, AES.MODE_CBC, iv)
out_file.write(salt)
finished = False
while not finished:
chunk = in_file.read(1024 * bs)
if len(chunk) == 0 or len(chunk) % bs != 0: #final block
padding_length = (bs - len(chunk) % bs) or bs
chunk += str.encode(padding_length * chr(padding_length))
finished = True
out_file.write(cipher.encrypt(chunk))
password = 'ABCDE' # some password
with open("some_file.bin", "rb") as in_file, open("enc_some_file.enc", "wb") as out_file:
encrypt(in_file, out_file, password)
Update:
I am updating this question regarding my try with WinCrypt. I am trying to compile from VS CODE using MSYS64 g++ compiler on Windows. Here is the code that I am trying to run. I also have some additional libraries to help me with the client-server part, such as libcurlpp and libcurl.
#include <string>
#include <sstream>
#include <conio.h>
#include <iostream>
#include <fstream>
#include <curlpp/cURLpp.hpp>
#include <curlpp/Easy.hpp>
#include <curlpp/Options.hpp>
#include <wincrypt.h>
#include <windows.h>
#define AES_KEY_SIZE 32
#define IN_CHUNK_SIZE (AES_KEY_SIZE * 10) // a buffer must be a multiple of the key size
#define OUT_CHUNK_SIZE (IN_CHUNK_SIZE * 2) // an output buffer (for encryption) must be twice as big
using namespace std;
string host = ""; #some host
int main(void)
{
curlpp::Easy req;
req.setOpt(new curlpp::options::Url(host));
ofstream myfile;
myfile.open("enc_calc.enc", ios::out | ios::binary);
myfile << req;
myfile.close();
getch();
wchar_t *in_file = (wchar_t *)"enc_calc.enc";
wchar_t *out_file = (wchar_t *)"calc.dll";
wchar_t default_key[] = L"ABCDE";
wchar_t *key_str = default_key;
const size_t len = lstrlenW(key_str);
const size_t key_size = len * sizeof(key_str[0]);
const wchar_t *filename1 = (const wchar_t *)"enc_calc.enc";
const wchar_t *filename2 = (const wchar_t *)"calc.dll";
HANDLE hInpFile = CreateFileW(filename1, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hInpFile == INVALID_HANDLE_VALUE) {
printf("Cannot open input file!\n");
system("pause");
return (-1);
}
HANDLE hOutFile = CreateFileW(filename2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hOutFile == INVALID_HANDLE_VALUE) {
printf("Cannot open output file!\n");
system("pause");
return (-1);
}
DWORD dwStatus = 0;
BOOL bResult = FALSE;
wchar_t info[] = L"Microsoft Enhanced RSA and AES Cryptographic Provider";
HCRYPTPROV hProv;
if (!CryptAcquireContextW(&hProv, NULL, info, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
dwStatus = GetLastError();
printf("CryptAcquireContext failed: %x\n", dwStatus);
CryptReleaseContext(hProv, 0);
system("pause");
return dwStatus;
}
HCRYPTHASH hHash;
if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)) {
dwStatus = GetLastError();
printf("CryptCreateHash failed: %x\n", dwStatus);
CryptReleaseContext(hProv, 0);
system("pause");
return dwStatus;
}
if (!CryptHashData(hHash, (BYTE*)key_str, key_size, 0)) {
DWORD err = GetLastError();
printf("CryptHashData Failed : %#x\n", err);
system("pause");
return (-1);
}
printf("[+] CryptHashData Success\n");
HCRYPTKEY hKey;
if (!CryptDeriveKey(hProv, CALG_AES_128, hHash, 0, &hKey)) {
dwStatus = GetLastError();
printf("CryptDeriveKey failed: %x\n", dwStatus);
CryptReleaseContext(hProv, 0);
system("pause");
return dwStatus;
}
printf("[+] CryptDeriveKey Success\n");
const size_t chunk_size = IN_CHUNK_SIZE;
BYTE *chunk = new BYTE[chunk_size];
DWORD out_len = 0;
BOOL isFinal = FALSE;
DWORD readTotalSize = 0;
DWORD inputSize = GetFileSize(hInpFile, NULL);
while (bResult = ReadFile(hInpFile, chunk, IN_CHUNK_SIZE, &out_len, NULL)) {
if (0 == out_len) {
break;
}
readTotalSize += out_len;
if (readTotalSize >= inputSize) {
isFinal = TRUE;
printf("Final chunk set, len: %d = %x\n", out_len, out_len);
}
if (!CryptDecrypt(hKey, NULL, isFinal, 0, chunk, &out_len)) {
printf("[-] CryptDecrypt failed: %x\n", GetLastError());
break;
}
DWORD written = 0;
if (!WriteFile(hOutFile, chunk, out_len, &written, NULL)) {
printf("writing failed!\n");
break;
}
memset(chunk, 0, chunk_size);
}
delete[]chunk; chunk = NULL;
CryptDestroyHash(hHash);
CryptDestroyKey(hKey);
CryptReleaseContext(hProv, 0);
CloseHandle(hInpFile);
CloseHandle(hOutFile);
printf("Finished. Processed %#x bytes.\n", readTotalSize);
return 0;
}
The errors I'm getting are regarding the windows.h library, such as:
"ULONG does not name a type" and other types in windows. and at runtime: "Cannot Open input file", not sure why, even tho the file is downloaded in the current folder and I'm trying to open it as such in the code.
Suppose I have a usb drive with two partition e:, f:. How do I know from which offset the partition e: or f: starts so that I can write raw data starting from that offset. I could not find any function that would provide me the offset in c++. In Dos I could easily get this with wmic partition get Index, Name, StartingOffset.
To get the StartingOffset of partitions in a Physical Drive(such as \\\\.\\PhysicalDrive1), you could use IOCTL_DISK_GET_DRIVE_LAYOUT_EX to get PARTITION_INFORMATION_EX arrays for each partition:
#include <windows.h>
#include <stdio.h>
#define wszDrive L"\\\\.\\PhysicalDrive1"
int wmain(int argc, wchar_t* argv[])
{
HANDLE hDevice = INVALID_HANDLE_VALUE; // handle to the drive to be examined
BOOL bResult = FALSE; // results flag
DWORD junk = 0; // discard results
DWORD error;
DWORD szNewLayout = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + sizeof(PARTITION_INFORMATION_EX) * 4 * 25;
hDevice = CreateFileW(wszDrive, // drive to open
GENERIC_READ, // no access to the drive
FILE_SHARE_READ,
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
0); // do not copy file attributes
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
{
error = GetLastError();
printf("CreateFileW error: %d\n", error);
return -1;
}
DRIVE_LAYOUT_INFORMATION_EX* pdg = (DRIVE_LAYOUT_INFORMATION_EX*)malloc(szNewLayout);
if (pdg == NULL)
{
error = GetLastError();
printf("malloc error: %d\n", error);
CloseHandle(hDevice);
return -1;
}
ZeroMemory(pdg, szNewLayout);
bResult = DeviceIoControl(hDevice, // device to be queried
IOCTL_DISK_GET_DRIVE_LAYOUT_EX, // operation to perform
NULL, 0, // no input buffer
pdg, szNewLayout,// sizeof(*pdg)*2, // output buffer
&junk, // # bytes returned
(LPOVERLAPPED)NULL); // synchronous I/O
if (!bResult)
{
error = GetLastError();
printf("DeviceIoControl error: %d\n", error);
free(pdg);
CloseHandle(hDevice);
return -1;
}
for (int i = 0; i < pdg->PartitionCount; i++) {
printf("partition %d: %lld\n", i, pdg->PartitionEntry[i].StartingOffset.QuadPart);
}
free(pdg);
CloseHandle(hDevice);
return 0;
}
To get the StartingOffset of a specified partition(such as \\\\.\\E:), you could use IOCTL_DISK_GET_PARTITION_INFO_EX:
#include <windows.h>
#include <stdio.h>
#define wszDrive L"\\\\.\\E:"
int wmain(int argc, wchar_t* argv[])
{
HANDLE hDevice = INVALID_HANDLE_VALUE; // handle to the drive to be examined
BOOL bResult = FALSE; // results flag
DWORD junk = 0; // discard results
DWORD error;
PARTITION_INFORMATION_EX piex;
ZeroMemory(&piex, sizeof(PARTITION_INFORMATION_EX));
hDevice = CreateFileW(wszDrive, // drive to open
GENERIC_READ, // no access to the drive
FILE_SHARE_READ,
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
0); // do not copy file attributes
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
{
error = GetLastError();
printf("CreateFileW error: %d\n", error);
return -1;
}
bResult = DeviceIoControl(hDevice,
IOCTL_DISK_GET_PARTITION_INFO_EX,
NULL, 0,
&piex, sizeof(PARTITION_INFORMATION_EX),
&junk,
(LPOVERLAPPED)NULL);
if (!bResult)
{
error = GetLastError();
printf("DeviceIoControl error: %d\n", error);
CloseHandle(hDevice);
return -1;
}
wprintf(L"%s StartingOffset: %lld\n", wszDrive, piex.StartingOffset.QuadPart);
CloseHandle(hDevice);
return 0;
}
I have a measurment device and want to make a series of measurments and store them to a file.
For this I need to read out the com port properly. All I get back with this code is some weird signs.
#include <windows.h>
#include <process.h>
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
int main() {
// opening the serial port
HANDLE hSerial;
fprintf(stderr, "Opening serial port...");
hSerial = CreateFile("\\\\.\\COM2",
GENERIC_READ | GENERIC_WRITE, 0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hSerial == INVALID_HANDLE_VALUE) {
fprintf(stderr, "Error\n");
CloseHandle(hSerial);
return 1;
} else
fprintf(stderr, "OK\n");
// settings to communicate with device
DCB dcbSerialParams;
ZeroMemory(&dcbSerialParams, sizeof(dcbSerialParams));
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
if (!GetCommState(hSerial, &dcbSerialParams)) {
//error getting state
fprintf(stderr,"error getting state ... ");
}
dcbSerialParams.BaudRate = 9600;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
if (!SetCommState(hSerial, &dcbSerialParams)) {
//error setting state
fprintf(stderr,"error setting state ...");
}
char out_message[] = "fetch?"; // request for the device to send voltage and
current
char in_message[32];
DWORD BytesToWrite = sizeof(out_message);
DWORD BytesWritten;
DWORD BytesToRead = sizeof(in_message);
DWORD BytesRead;
WriteFile(hSerial, out_message, BytesToWrite, &BytesWritten, NULL);
ReadFile(hSerial, &in_message, BytesToRead, &BytesRead, NULL);
string buffer;
for (unsigned int i = 0; i < sizeof(in_message); i++) {
buffer += in_message[i];
}
buffer[sizeof(in_message) - 1] = '\0';
// try outs of different outputs
cout << buffer << "\n";
const char*c = buffer.c_str();
printf("%s\n",c);
CloseHandle(hSerial);
return 0;
}
I guess I cannot write to com an read out immediately?
Or is there a mistake in the conversion in_message to buffer?
Here is my attempt:
// ConsoleApplication1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include <iostream>
#include <string>
// Forward declarations:
void append(LPCTSTR, LPCVOID, DWORD);
void readTail(LPCTSTR, LPVOID, DWORD);
int main()
{
LPCTSTR fn = L"C:/kaiyin/kybig.out";
LPCVOID buf = "eeeee";
append(fn, buf, 5);
LPVOID buf1 = "";
readTail(fn, buf1, 5);
std::cout << (char*) buf1 << std::endl;
printf("hello world\n");
std::string s = "";
std::getline(std::cin, s);
return 0;
}
void append(LPCTSTR filename, LPCVOID buf, DWORD writeSize) {
LARGE_INTEGER size;
size.QuadPart = 0;
HANDLE fh = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
GetFileSizeEx(fh, &size);
SetFilePointerEx(fh, size, NULL, FILE_BEGIN);
WriteFile(fh, buf, writeSize, NULL, NULL);
CloseHandle(fh);
}
void readTail(LPCTSTR filename, LPVOID buf, DWORD readSize) {
LARGE_INTEGER size;
size.QuadPart = 0;
HANDLE fh = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
GetFileSizeEx(fh, &size);
size.QuadPart -= readSize;
SetFilePointerEx(fh, size, NULL, FILE_BEGIN);
ReadFile(fh, buf, readSize, NULL, NULL);
CloseHandle(fh);
}
The append function seems to increase the file size by the correct number (5 bytes), but printing the last 5 byte to in the console doesn't show anything.
What went wrong?
You have not allocated buffer for your result:
LPVOID buf1 = "";
readTail(fn, buf1, 5);
buf1 is only a pointer to empty string, what you want is some buffer where to put your results:
BYTE buf1[10] = { 0 };
readTail(fn, buf1, 5);
Also, you are appending initialy to existing file (due to OPEN_EXISTING),so makesure you have an empty C:/kaiyin/kybig.out file.
Just for the record, here is the modified code according to suggestions from #marcinj :
// ConsoleApplication1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include <iostream>
#include <string>
// Forward declarations:
void append(LPCTSTR, LPCVOID, DWORD);
void readTail(LPCTSTR, LPVOID, DWORD);
void truncateTail(LPCTSTR, long);
int main()
{
LPCTSTR fn = L"C:/kaiyin/kybig.out";
char buf[] = "helloWorld";
append(fn, buf, 10);
BYTE buf1[10] = {0};
readTail(fn, buf1, 5);
std::cout << (char*) buf1 << std::endl;
truncateTail(fn, 5);
for (int i = 0; i < 10; i++) {
buf1[i] = 0;
}
readTail(fn, buf1, 5);
std::cout << (char*) buf1 << std::endl;
printf("End of program\n");
std::string s = "";
std::getline(std::cin, s);
return 0;
}
void append(LPCTSTR filename, LPCVOID buf, DWORD writeSize) {
LARGE_INTEGER size;
size.QuadPart = 0;
HANDLE fh = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
GetFileSizeEx(fh, &size);
SetFilePointerEx(fh, size, NULL, FILE_BEGIN);
WriteFile(fh, buf, writeSize, NULL, NULL);
CloseHandle(fh);
}
void readTail(LPCTSTR filename, LPVOID buf, DWORD readSize) {
LARGE_INTEGER size;
size.QuadPart = 0;
HANDLE fh = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
GetFileSizeEx(fh, &size);
size.QuadPart -= readSize;
SetFilePointerEx(fh, size, NULL, FILE_BEGIN);
ReadFile(fh, buf, readSize, NULL, NULL);
CloseHandle(fh);
}
void truncateTail(LPCTSTR filename, long truncateSize) {
LARGE_INTEGER size;
size.QuadPart = 0;
HANDLE fh = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fh == INVALID_HANDLE_VALUE) {
std::cerr << GetLastError();
return;
}
GetFileSizeEx(fh, &size);
size.QuadPart -= truncateSize;
SetFilePointerEx(fh, size, NULL, FILE_BEGIN);
if (SetEndOfFile(fh) == 0) {
std::cerr << GetLastError();
return;
}
CloseHandle(fh);
}
The problem I'm having: CreateFile returns a handle of 0x194. ReadFileEx is saying that this handle is invalid. (Error 6.) Any ideas? The argument passed in is "C:\testfile.txt", which is a valid text file I made in Notepad. Despite being a C++ programmer for the last 12 years, this is my first time writing anything with "windows.h" or threads.
#include "stdafx.h"
#include "stdio.h"
#include "windows.h"
using namespace System;
int main(int argc, char **argv)
{
if (argc != 2)
{
printf("To display a file, you must enter the filename as the only command argument.");
scanf("\n");
return 0;
}
HANDLE file;
int nameLen = (strlen(argv[1]) + 1);
wchar_t *filename = new wchar_t[nameLen];
if (filename == 0)
{
printf("To display a file, you must enter the filename as the only command argument.");
scanf("\n");
return 0;
}
memset(filename, 0, nameLen);
::MultiByteToWideChar(CP_ACP, NULL, argv[1], -1, filename, nameLen);
file = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (file == NULL)
{
printf("A valid filename is required.");
scanf("\n");
return 0;
}
char *buffer;
buffer = new char[1024];
OVERLAPPED overlapped;
overlapped.Offset = overlapped.OffsetHigh = 0;
ReadFileEx(file, &buffer, 1024, &overlapped, NULL);
WaitForSingleObject(&file, 0);
if (GetLastError() != ERROR_SUCCESS)
{
printf("A valid file is required., Error: %d", GetLastError());
scanf("\n");
return 0;
}
printf("%s", buffer);
scanf("\n");
delete buffer;
return 0;
}
My guess is to change
ReadFileEx(&file, &buffer, 1024, &overlapped, NULL);
to
ReadFileEx(file, &buffer, 1024, &overlapped, NULL);