Related
I made a server and a client in winapi.
Client sends an number and a base and the server returns the number in that base.
My problem that it works in Windows 10, but it doesn't work in Windows 7 and I don't understand why. Some help?
Client:
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <assert.h>
#include <windows.h>
#include <string>
#define BUFFSIZE 512
using namespace std;
int main()
{
LPDWORD bytesRead = 0;
char res[50];
int num, base;
LPCTSTR Roura = TEXT("\\\\.\\pipe\\pipeline");
HANDLE h = CreateFile(Roura, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
while (true) {
for (int i = 0; i < 50; i++) {
res[i] = 0;
}
printf("Number: ");
cin >> num;
WriteFile(h, &num, sizeof(int), NULL, NULL);
if (num == 0) {
CloseHandle(h);
return 0;
}
printf("Base: ");
cin >> base;
WriteFile(h, &base, sizeof(int), NULL, NULL);
ReadFile(h, res, BUFFSIZE, bytesRead, NULL);
cout << res << endl;
}
return 0;
}
Server:
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <assert.h>
#include <windows.h>
#include <string>
#define _CRT_SECURE_NO_WARNINGS
#define BUFFSIZE 512
using namespace std;
int main()
{
int num, base;
LPDWORD bytesRead = 0;
char result[50];
char end[] = {"\0"};
LPCTSTR Roura = TEXT("\\\\.\\pipe\\pipeline");
HANDLE h = CreateNamedPipe(Roura, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 1, BUFFSIZE, BUFFSIZE, 0, NULL);
assert(h != INVALID_HANDLE_VALUE);
if (!ConnectNamedPipe(h, NULL)) return -1;
while (true) {
ReadFile(h, &num, BUFFSIZE, bytesRead, NULL);
if (num == 0) {
CloseHandle(h);
return 0;
}
ReadFile(h, &base, BUFFSIZE, bytesRead, NULL);
_itoa(num, result, base);
WriteFile(h, result, strlen(result), NULL, NULL);
}
return 0;
}
#define BUFFSIZE 512
int num, base;
LPDWORD bytesRead = 0;
ReadFile(h, &num, BUFFSIZE, bytesRead, NULL);
this code complete of errors. need use
int num, base;
DWORD bytesRead;
ReadFile(h, &num, sizeof(num), &bytesRead, NULL);
instead. crash faster of all by bytesRead== 0
when
If lpOverlapped is NULL, lpNumberOfBytesRead cannot be NULL.
however this true on win7, but on say win10 - system let have lpNumberOfBytesRead == 0 - so no crash here
also this
WriteFile(h, &num, sizeof(int), NULL, NULL);
again - here already only 1 error compare ReadFile call
If lpOverlapped is NULL, lpNumberOfBytesWritten cannot be NULL.
why ?
that it works in Windows 10, but it doesn't work in Windows 7
this is because begin from win 8.1 (if I not mistake) code of ReadFile/WriteFile check lpNumberOfBytes parameter and if it ==0 not assign to it actual number of bytes read or written. but on windows 7 system not do this check and unconditionally write data by 0 address
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);
}
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.
I wrote this code that is SUPPOSED to write to a file on an ftp server, but it doesn't work. The file stays 0 bytes. There are also no errors. Here's my code:
#include <windows.h>
#include <wininet.h>
#include <stdio.h>
int main()
{
int error=0;
char buffer[256];
char *text="Hello world.";
HINTERNET hOpen=InternetOpen("",INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,INTERNET_FLAG_PASSIVE);
InternetGetLastResponseInfo((LPDWORD)error,(LPSTR)buffer,(LPDWORD)256);
printf("hOpen:%d:%s\n",error,buffer);
HINTERNET hConnect=InternetConnect(hOpen,"diabloip.host22.com",INTERNET_DEFAULT_FTP_PORT,"MY_USER_NAME","MY_PASSWORD",INTERNET_SERVICE_FTP,INTERNET_FLAG_PASSIVE,0);
InternetGetLastResponseInfo((LPDWORD)error,(LPSTR)buffer,(LPDWORD)256);
printf("hConnect:%d:%s\n",error,buffer);
HINTERNET hFile=FtpOpenFile(hConnect,"diabloip.host22.com/public_html/log.txt",GENERIC_WRITE,FTP_TRANSFER_TYPE_ASCII,0);
InternetGetLastResponseInfo((LPDWORD)error,(LPSTR)buffer,(LPDWORD)256);
printf("hFile:%d:%s\n",error,buffer);
InternetWriteFile(hFile,text,strlen(text),NULL);
return 0;
}
The problem is passing NULL as the last parameter to InternetWriteFile. It is not an optional parameter and if you had error checking for that call as the rest you'd see GetLastError returns 87, or ERROR_INVALID_PARAMETER.
This works correctly and cleans up some of the other issues with incorrect parameters and the excessive casting that masks the issues.
#include <windows.h>
#include <wininet.h>
#include <stdio.h>
#pragma comment(lib, "wininet.lib")
void PrintStatus(const char* title)
{
DWORD error = 0;
DWORD sz = 256;
char buffer[256];
InternetGetLastResponseInfo(&error, buffer, &sz);
printf("%s:%u:%s\n", title, error, buffer);
}
int main()
{
const char *text = "Hello world.";
HINTERNET hOpen = InternetOpen("", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_PASSIVE);
PrintStatus("hOpen");
HINTERNET hConnect = InternetConnect(hOpen, "localhost", INTERNET_DEFAULT_FTP_PORT, "test", "test", INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);
PrintStatus("hConnect");
HINTERNET hFile = FtpOpenFile(hConnect, "log.txt", GENERIC_WRITE, FTP_TRANSFER_TYPE_ASCII, 0);
PrintStatus("hFile");
DWORD wb = 0;
BOOL Success = InternetWriteFile(hFile, text, strlen(text), &wb);
if(!Success)
{
DWORD err = GetLastError();
printf("InternetWriteFile - Error = %u\n", err);
}
PrintStatus("InternetWriteFile");
InternetCloseHandle(hOpen);
return 0;
}
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);