I'm new to Win32 programming.
I'm trying to pass a HANDLE obtained using CreateFile() to a function in a DLL.
But upon trying to read bytes, dwBytesRead says 0.
Am I allowed to pass HANDLEs to DLL entries? I read here [Writing DLLs] that resources of the caller do not belong to callee, and hence I should not call CloseHandle() or things like free() for malloc() in caller.
Is my understanding correct? Kindly point me in the right direction. Here's the code:
main.c
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#define BUFFERSIZE 5
int __declspec( dllimport ) hello( HANDLE );
void __cdecl _tmain(int argc, TCHAR *argv[])
{
HANDLE hFile;
printf("\n");
if( argc != 2 )
{
printf("Usage Error: Incorrect number of arguments\n\n");
_tprintf(TEXT("Usage:\n\t%s <text_file_name>\n"), argv[0]);
return;
}
hFile = CreateFile(argv[1], // file to open
GENERIC_READ, // open for reading
FILE_SHARE_READ, // share for reading
NULL, // default security
OPEN_EXISTING, // existing file only
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, // normal file
NULL); // no attr. template
if (hFile == INVALID_HANDLE_VALUE)
{
_tprintf(TEXT("Terminal failure: unable to open file \"%s\" for read.\n"), argv[1]);
return;
}
printf( "Entered main, calling DLL.\n" );
hello(hFile);
printf( "Back in main, exiting.\n" );
CloseHandle(hFile);
}
hello.c
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#define BUFFERSIZE 5
DWORD g_BytesTransferred = 0;
VOID CALLBACK FileIOCompletionRoutine(
__in DWORD dwErrorCode,
__in DWORD dwNumberOfBytesTransfered,
__in LPOVERLAPPED lpOverlapped )
{
_tprintf(TEXT("Error code:\t%x\n"), dwErrorCode);
_tprintf(TEXT("Number of bytes:\t%x\n"), dwNumberOfBytesTransfered);
g_BytesTransferred = dwNumberOfBytesTransfered;
}
int __declspec( dllexport ) hello( HANDLE hFile )
{
DWORD dwBytesRead = 0;
char ReadBuffer[BUFFERSIZE] = {0};
OVERLAPPED ol = {0};
if( FALSE == ReadFileEx(hFile, ReadBuffer, BUFFERSIZE-1, &ol, FileIOCompletionRoutine) )
{
DWORD lastError = GetLastError();
printf("Terminal failure: Unable to read from file.\n GetLastError=%08x\n", lastError);
return lastError;
}
dwBytesRead = g_BytesTransferred;
if (dwBytesRead > 0 && dwBytesRead <= BUFFERSIZE-1)
{
ReadBuffer[dwBytesRead]='\0';
printf("Data read from file (%d bytes): \n", dwBytesRead);
printf("%s\n", ReadBuffer);
}
else if (dwBytesRead == 0)
{
printf("No data read from file \n");
}
else
{
printf("\n ** Unexpected value for dwBytesRead ** \n");
}
printf( "Hello from a DLL!\n" );
return( 0 );
}
You are missing the SleepEx(5000, TRUE) call from the example.
You are using async-io, in which case you will receive a callback when the read occurs. If you don't wait for the callback you may get 0 bytes read depending on when the callback is triggered.
Related
I'm using the EnumProcesses function to get all process IDs on the system. Then I iterate over each process ID and pass it to OpenProcess to get a process handle, which I then pass to GetProcessImageFileNameA to get the process name.
Here's a code snippet:
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <Psapi.h>
DWORD GetProcessName(DWORD processID, TCHAR lpFileName, DWORD nSize)
{
HANDLE hProcess;
DWORD pLength;
// Get process handle
hProcess = OpenProcess(
PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
FALSE,
processID
);
if ( !hProcess )
return NULL;
// Write process name to buffer
if ( pLength = GetProcessImageFileNameA(hProcess, lpFileName, nSize) )
{
CloseHandle(hProcess);
return pLength;
}
CloseHandle(hProcess);
}
int main(void)
{
DWORD processIDs[PROC_ID_SIZE], cbNeeded, cProcess;
unsigned int i;
// Get process IDs
if ( !EnumProcesses(processIDs, sizeof(processIDs), &cbNeeded) )
return 1;
// Get process ID count
cProcess = cbNeeded / sizeof(DWORD);
printf("Number of Processes: %u | Size of Process Array: %d\n", cProcess, (int)sizeof(processIDs));
// Get the process name of each process
for (i = 0; i < cProcess; i++)
{
if ( processIDs[i] != 0 )
{
// The access violation is happening here
TCHAR processName[MAX_PATH];
GetProcessName(processIDs[i], processName, sizeof(processName));
printf("Process name: %s\n", (char*)processName);
}
}
return 0;
}
It compiles fine, but I get this runtime error:
Exception thrown at 0x00007FF985433338 (KernelBase.dll) in QuickSave.exe: 0xC0000005: Access violation writing location 0x000000000000F8D0.
I have a suspicion it's because I'm declaring processName from outside of the function's scope. When I create another function and declare processName within that function's scope, it works. I'm not entirely sure why.
DWORD PrintProcessName(DWORD processID)
{
HANDLE hProcess;
TCHAR processName[MAX_PATH];
DWORD pLength;
// Get process handle
hProcess = OpenProcess(
PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
FALSE,
processID
);
if (!hProcess)
return NULL;
// Write process name to buffer and print it
if ( pLength = GetProcessImageFileNameA(hProcess, processName, sizeof(processName)) )
{
printf("Process name: %s\n", (char*)processName);
return pLength;
}
CloseHandle(hProcess);
}
I'm still learning C so I'm probably making a newbie mistake, but hopefully someone can help me make sense of what's going on here.
I have fixed your code. The main errors was bad declaration of GetProcessName, wrong size passed for processName size, incorrect printf format specification, function doesn't always return a value, missing error checks.
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <Psapi.h>
#define PROC_ID_SIZE 1000
DWORD GetProcessName(DWORD processID, TCHAR *lpFileName, DWORD nSize)
{
HANDLE hProcess;
DWORD pLength;
// Get process handle
hProcess = OpenProcess(
PROCESS_QUERY_LIMITED_INFORMATION,
FALSE,
processID
);
if (!hProcess)
return 0;
// Write process name to buffer
pLength = GetProcessImageFileNameW(hProcess, lpFileName, nSize);
CloseHandle(hProcess);
return pLength;
}
int main(void)
{
DWORD processIDs[PROC_ID_SIZE], cbNeeded, cProcess;
unsigned int i;
// Get process IDs
if (!EnumProcesses(processIDs, sizeof(processIDs), &cbNeeded))
return 1;
// Get process ID count
cProcess = cbNeeded / sizeof(DWORD);
printf("Number of Processes: %u | Size of Process Array: %d\n", cProcess, (int)sizeof(processIDs));
// Get the process name of each process
for (i = 0; i < cProcess; i++)
{
if (processIDs[i] != 0)
{
// The access violation is happening here
TCHAR processName[MAX_PATH];
if (GetProcessName(processIDs[i], processName, sizeof(processName)/sizeof(processName[0])))
printf("Process name: %ls\n", processName);
}
}
return 0;
}
I have been coding on C/C++ for a while but now I have faced a major problem which I can not resolve. I am trying to communicate with COM port. First I am sending data with WriteFile(), this part works.But when it comes to receiving an answer from the port with ReadFile(), I do not get anything.
Here is the code:
#include <stdlib.h>
#include <windows.h>
#include <stdio.h>
#include <conio.h>
int main(int argc, char *argv[])
{
int n=0;
DCB dcb={0};
HANDLE hCom;
BOOL fSuccess;
char *pcCommPort = "COM3";
DWORD dwBytesRead=0;
DWORD dwRead;
DWORD dwBytesWrite=0;
DWORD dwWrite=0;
/***************************************CommTimeouts******************************************/
COMMTIMEOUTS timeouts={0};
timeouts.ReadIntervalTimeout=200;
//timeouts.ReadTotalTimeoutConstant=1;
//timeouts.ReadTotalTimeoutMultiplier=1;
timeouts.WriteTotalTimeoutConstant=2;
//timeouts.WriteTotalTimeoutMultiplier=1;
/*******************************************Handle*******************************************/
hCom = CreateFile( pcCommPort,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ, // must be opened with exclusive-access
NULL, // no security attributes
OPEN_EXISTING, // must use OPEN_EXISTING
FILE_ATTRIBUTE_NORMAL, // not overlapped I/O
NULL // hTemplate must be NULL for comm devices
);
/***************************************SET*UP*COM*PORT**************************************/
if (hCom == INVALID_HANDLE_VALUE)
{
printf ("CreateFile failed with error %d.\n", GetLastError());
CloseHandle(hCom);
return (1);
}
if(!SetCommTimeouts(hCom, &timeouts))
{
/*Well, then an error occurred*/
}
fSuccess = GetCommState(hCom, &dcb);
if (!fSuccess)
{
/*More Error Handling*/
printf ("GetCommState failed with error %d.\n", GetLastError());
CloseHandle(hCom);
return (2);
}
dcb.BaudRate = 9600; // set the baud rate
dcb.ByteSize = 8; // data size, xmit, and rcv
dcb.Parity = EVENPARITY; // no parity bit
dcb.StopBits = ONESTOPBIT; // one stop bit
fSuccess = SetCommState(hCom, &dcb);
if (!fSuccess)
{
printf ("SetCommState failed. Error: %d.\n", GetLastError());
CloseHandle(hCom);
return (3);
}
printf ("Serial port %s successfully configured.\n", pcCommPort);
// return (0);
/*************************************Writing************************************************/
char bytes_to_send[] = {'36'};
if(!WriteFile(hCom, bytes_to_send, 2, &dwBytesWrite, NULL))
{
fprintf(stderr, "Error\n");
CloseHandle(hCom);
return 1;
}
printf("dwBytesWrite = %d | %x\n", dwBytesWrite, (dwBytesWrite));
/*************************************Reading************************************************/
char bytes_to_receive[7];
if(!ReadFile(hCom, bytes_to_receive, 7, &dwBytesRead, NULL)){
printf ("SetCommState failed. Error: %d.\n", GetLastError());
CloseHandle(hCom);
return (4);
} else {
printf("Bytes read %d -> %d\n",dwBytesRead, bytes_to_receive);}
/********************************************************************************************/
CloseHandle(hCom);
return(0);
}
There is a file pointer, both for read and write. After the WriteFile it is at the end of the file. If you try to read from it, you will read at the end of the file. To read what you just wrote you have to reposition the file pointer at the start of the file, using the SetFilePointer function:
SetFilePointer(hCom, 0, NULL, FILE_BEGIN);
I have tried compiling a windows executable using the win32api, however I have encountered many road blocks.
First thing to try was gcc -mno-cygwin [...] which results in gcc: error: unrecognized command line option '-mno-cygwin' which is strange since man gcc|grep -e '-mno-cygwin' is successful and mingw is installed.
No matter what other header files I try to include I always end up with unsatisfied circular include dependencies (a.h requires b.h requires a.h). What set of header files are required to properly compile an executable based on the win32 api?
header files I have tried:
w32api/winnt.h
w32api/ddk/ntddk.h
w32api/Windows.h
w32api/ntdef.h
source code:
$ cat source.c
#include <w32api/winnt.h>
#include <w32api/ddk/ntddk.h>
int main(int argc, char **argv) {
PHANDLE hProcess;
CLIENT_ID processId;
processId.UniqueProcess = (HANDLE) 1000;
processId.UniqueThread = 0;
NtOpenProcess(&hProcess, PROCESS_VM_READ|PROCESS_VM_WRITE, 0, &processId);
return 0;
}
$ gcc -o a.exe -I/usr/include/w32api -I/usr/include/w32api/ddk source.c
In file included from memoryEdit.c:1:0:
/usr/include/w32api/winnt.h:291:11: error: unknown type name 'CONST'
typedef CONST WCHAR *LPCWCH,*PCWCH;
^
[...]
$ gcc --version
gcc (GCC) 5.4.0
$ uname -a
CYGWIN_NT-6.1 HOST_NAME 2.5.2(0.297/5/3) 2016-06-23 14:29 x86_64 Cygwin
gcc -mno-cygwin has been removed ages ago.
If you want to compile a windows program you need to use not the gcc compiler, that is cygwin to cygwin, but the cross compilers cygwin to windows.
There are 2 package variants depending on the arch:
mingw64-i686-gcc
mingw64-x86_64-gcc
I had no troubles just now with a compilation in Eclipse/gcc. Here's my testfile:
/*
============================================================================
Name : win32gcctest.c
Author : Clark Thomborson
Version : 1.0
Copyright : Copyleft
Description : Testing winapi synchronous file access within Cygwin
============================================================================
*/
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#include <fileapi.h>
void my_write(char* fname) {
HANDLE hFile;
char DataBuffer[] = "This is some test data to write to the file.";
DWORD dwBytesToWrite = (DWORD) strlen(DataBuffer);
DWORD dwBytesWritten = 0;
BOOL bErrorFlag = FALSE;
hFile = CreateFile(fname, // name of the write
GENERIC_WRITE, // open for writing
0, // do not share
NULL, // default security
CREATE_ALWAYS, // overwrite any existing file
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attr. template
if (hFile == INVALID_HANDLE_VALUE) {
DWORD last_err = GetLastError();
printf("Error code %d: unable to open file \"%s\" for write.\n", last_err, fname);
exit( last_err );
}
printf("Writing %d bytes to %s.\n", dwBytesToWrite, fname);
bErrorFlag = WriteFile(hFile,
DataBuffer, // start of data to write
dwBytesToWrite, // number of bytes to write
&dwBytesWritten, // number of bytes that were written
NULL); // no overlapped structure
if (FALSE == bErrorFlag) {
DWORD last_err = GetLastError();
printf("Error code %d: unable to write to file \"%s\".\n", last_err, fname);
exit( GetLastError() );
exit( last_err );
} else {
if (dwBytesWritten != dwBytesToWrite) {
// This is an error because a synchronous write that results in
// success (WriteFile returns TRUE) should write all data as
// requested. This would not necessarily be the case for
// asynchronous writes.
printf("Error: dwBytesWritten != dwBytesToWrite\n" );
exit( EXIT_FAILURE );
} else {
printf("Wrote %d bytes to %s successfully.\n", dwBytesWritten, fname);
}
}
CloseHandle(hFile);
}
HANDLE my_open_for_read(char* fname) {
HANDLE hFile;
hFile = CreateFile(
fname,
GENERIC_READ,
FILE_SHARE_DELETE, // another process may delete this file while this handle is open
NULL, // no security attributes
OPEN_EXISTING, // returns error if file not found
FILE_ATTRIBUTE_NORMAL, // no special attributes, so can't do async IO
NULL // no attributes will be copied from another file
);
if (hFile == INVALID_HANDLE_VALUE) {
DWORD last_err = GetLastError();
printf("Error code %d: unable to open file \"%s\" for read.\n", last_err, fname);
exit( last_err );
}
return hFile;
}
ssize_t my_read(HANDLE hFile, void *buffer, size_t bytes_to_read) {
DWORD bytes_read;
if (ReadFile(hFile, buffer, bytes_to_read, &bytes_read, NULL)) {
return (ssize_t) bytes_read;
} else {
DWORD last_err = GetLastError();
printf("Error code %d: unable to read file.\n", last_err );
exit( last_err );
}
}
int main(void) {
char fname[32] = "test.txt";
my_write( fname );
printf("Reading %s.\n", fname);
char buff[1024];
HANDLE hFile = my_open_for_read( fname );
ssize_t nc = my_read( hFile, buff, 1023 ); // allow room for terminating byte
if( nc >= 0 ) {
buff[nc] = 0; // terminate string
printf("Read %d characters: %s", (int) nc, buff);
return EXIT_SUCCESS;
} else { // buggy my_read()
printf("Error %d", (int) nc );
return nc;
}
}
I am trying to share some data between 2 processes. The first writes the data in mapped file and the second reads it.
Here's my code so far:
First process:
#include "stdafx.h"
#include <Windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include<stdio.h>
#define BUF_SIZE 256
int _tmain(int argc, _TCHAR* argv[]) {
TCHAR szName[] = TEXT("Global\\MyFileMappingObject");
LPTSTR szMsg = TEXT("MESS");
HANDLE tokenH;
TOKEN_PRIVILEGES tp;
LUID luid;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &tokenH)) {
printf("OpenProcessToken error: %u\n", GetLastError());
return FALSE;
}
if (!LookupPrivilegeValue(NULL, SE_CREATE_GLOBAL_NAME, &luid)) {
printf("LookupPrivilegeValue error: %u\n", GetLastError());
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(tokenH, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),(PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) {
printf("AdjustTokenPrivileges error: %u\n", GetLastError());
return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}
CloseHandle(tokenH);
HANDLE hMapFile;
LPCTSTR pBuf;
hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
BUF_SIZE,
szName);
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not create file mapping object (%d).\n"),
GetLastError());
return 1;
}
pBuf = (LPTSTR)MapViewOfFile(hMapFile,
FILE_MAP_ALL_ACCESS,
0,
0,
BUF_SIZE);
if (pBuf == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(hMapFile);
return 1;
}
CopyMemory((PVOID)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR)));
UnmapViewOfFile(pBuf);
printf("Done\n");
CloseHandle(hMapFile);
return 0;
}
Second process:
#include "stdafx.h"
#include <Windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include <stdio.h>
#pragma comment(lib, "user32.lib")
#define BUF_SIZE 256
int _tmain(int argc, _TCHAR* argv[])
{
TCHAR szName[] = TEXT("Global\\MyFileMappingObject");
HANDLE tokenH;
TOKEN_PRIVILEGES tp;
LUID luid;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &tokenH);
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) {
printf("LookupPrivilegeValue error: %u\n", GetLastError());
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(tokenH, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) {
printf("AdjustTokenPrivileges error: %u\n", GetLastError());
return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}
CloseHandle(tokenH);
HANDLE hMapFile;
LPCTSTR pBuf;
hMapFile = OpenFileMapping(
FILE_MAP_ALL_ACCESS, // read/write access
FALSE, // do not inherit the name
szName); // name of mapping object
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not open file mapping object (%d).\n"),
GetLastError());
return 1;
}
pBuf = (LPTSTR)MapViewOfFile(hMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
if (pBuf == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(hMapFile);
return 1;
}
MessageBox(NULL, pBuf, TEXT("Process2"), MB_OK);
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
return 0;
}
The first process manages to write its data (I don't receive any error message and get the "Done" message), but the problem is with the the second process.
After "OpenFileMapping", I get from getLastError the code 2 which is for non-existent file. I run both processes as administrator.
Error 2 is ERROR_FILE_NOT_FOUND, which means the named mapping object does not exist at the time OpenFileMapping() is called.
In order to share a named kernel object between processes, both processes need to be running at the same time. Like other named kernel objects (events, mutexes, etc), a mapping object has a reference count associated with it, where each open handle increments the reference count. After all handles are closed, the object is destroyed.
So, when the first app unmaps its view and closes its handle to the mapping object, the object will be destroyed if the second app does not already have its own handle open to the same mapping object. Thus the object will not exist when the second app tries to open it.
I must read a binary file, but I have wrong output. I start from a txt file that contains:
1 100000 Romano Antonio 1250
2 150000 Fabrizi Aldo 2245
3 200000 Verdi Giacomo 11115
4 250000 Rossi Luigi 13630
I generate the relative binary file by with program:
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#define BUF_SIZE 1000
/*
* Problem1: use tchar.h and _tmain instead of
* int main (int argc, LPTSTR argv [])
* Sometimes it is needeed to see argv correctly
*/
int _tmain (int argc, LPTSTR argv [])
{
HANDLE hIn, hOut;
DWORD nIn, nOut;
CHAR buffer [BUF_SIZE];
if (argc != 3) {
fprintf (stderr, "Usage: cp file1 file2\n");
return 1;
}
hIn = CreateFile (argv[1], GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); /*Here hIn is created with read access*/
if (hIn == INVALID_HANDLE_VALUE) {
fprintf (stderr,
"Cannot open input file. Error: %x\n", GetLastError ());
return 2;
}
hOut = CreateFile (argv[2], GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hOut == INVALID_HANDLE_VALUE) {
fprintf (stderr,
"Cannot open output file. Error: %x\n", GetLastError ());
CloseHandle(hIn);
return 3;
}
while (ReadFile (hIn, buffer, BUF_SIZE, &nIn, NULL) && nIn > 0) {
/*hIn is the handle to the read file, buffer is a pointer to the buffer that receives the data read
from the file, BUF_SIZE is the maximum number of bytes to be read, &nIn is
the pointer to the variable that receives the n° of bytes read*/
/*
* Problem 2:
* During the last cycle less than BUF_SIZE characters may
* be read from file
* WriteFile (hOut, buffer, BUF_SIZE, &nOut, NULL);
* so write just the number of characters read
*/
WriteFile (hOut, buffer, nIn, &nOut, NULL); /*I write in file related hOut, the content of read file hIn is in buffer,
nIn is the n° of bytes to write, &nOut is a pointer to the variable that receives the number of bytes written*/
if (nIn != nOut) {
fprintf (stderr, "Fatal write error: %x\n", GetLastError ());
CloseHandle(hIn); CloseHandle(hOut);
return 4;
}
}
CloseHandle (hIn);
CloseHandle (hOut);
return 0;
}
Now I think that it gives me a binary file. Then, I have to read this binary file and put the data into a struct. My code is:
#if 1
#define UNICODE
#define _UNICODE
#endif
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#define L 30+1
#define SETFILEPOINTER_OVERLAPPING 1
#define N 3
#define BUF_SIZE 1000
struct myacc {
int id;
long int acc_number;
TCHAR surname[L];
TCHAR name[L];
int amount;
};
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hIn;
OVERLAPPED ov = {0, 0, 0, 0, NULL};
DWORD nIn,n;
//TCHAR c;
//TCHAR buffer[BUF_SIZE];
LARGE_INTEGER filePos;
struct myacc account;
if(argc != N) {
fprintf(stderr, "Error into arguments\n");
return 1;
}
hIn = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hIn == INVALID_HANDLE_VALUE) {
fprintf (stderr,"Cannot open input file. Error: %x\n", GetLastError ());
return 2;
}
n=1;
filePos.QuadPart = (n-1) * sizeof(struct myacc);
#if SETFILEPOINTER_OVERLAPPING
SetFilePointerEx (hIn, filePos, NULL, FILE_BEGIN);
while(ReadFile (hIn, &account, sizeof (struct myacc), &nIn, NULL) && nIn > 0) {
_tprintf (_T("-> %d %ld %s %s %d <-\n"), account.id, account.acc_number, account.surname, account.name, account.amount);
}
#else
ov.Offset = filePos.LowPart; /*Uso l'overlapped structure ov se ho asynchronous I/O*/
ov.OffsetHigh = filePos.HighPart;
while(ReadFile (hIn, &account, sizeof (struct myacc), &nIn, &ov) && nIn > 0) {
_tprintf (_T("-> %d %ld %s %s %d <-\n"), account.id, account.acc_number, account.surname, account.name, account.amount);
}
#endif
return 0;
}
Now, in this part of code
while(ReadFile (hIn, &account, sizeof (struct myacc), &nIn, NULL) && nIn > 0) {
_tprintf (_T("-> %d %ld %s %s %d <-\n"), account.id, account.acc_number, account.surname, account.name, account.amount);
}
the output is wrong, that is:
Why do I get this? I generate wrong bin file? Or I manage bad the output function? I hope you can help me.
Thank you in advance.
You believe that second program is wrong, but we don't know if it is wrong because the input for the second program is also wrong.
Input for the second program (also output of the first program) is supposed to be a binary file, but it is actually a text file, identical to the the input of the first program. It is identical because the first program is not making any kind of conversion. All it does is ReadFile(..., buffer, ..., &nIn, ...) immediately followed by WriteFile(..., buffer, nIn, ...). These two lines just copy all the data.
First program should use getline() (like described here, in a second method, line-based parsing) instead of ReadFile(), get all the data, populate one struct myacc object, and WriteFile contents of that object.