File Manipulation with the win32 API

Our first program starts by opening a file handle to a file we will create, testfile.txt. The file handle is opened using the CreateFile() call. This call returns a handle to the new file, or else it return INVALID_HANDLE_VALUE, which means there has been a problem. We will also acquire a handle to standard input using the GetStdHandle() API call.

We will then create a loop that reads in text from standard input via the ReadFile() call and writes it to the file via the WriteFile() call.

#include <Windows.h>
#include <stdio.h>

int _tmain(int argc, _TCHAR* argv[])
{
	DWORD dwBytesRead, dwBytesWritten, dwTotal;
	char szBuffer[512];
	HANDLE hIn;

	HANDLE hFile = CreateFile(
		"testfile.txt", // filename
		GENERIC_WRITE, //open for writing
		0, //no sharing
		NULL, //no security
		CREATE_NEW, //new file
		FILE_ATTRIBUTE_NORMAL, //no special attributes
		NULL); //no template file

	//check for error
	if(hFile == INVALID_HANDLE_VALUE){
		printf("Error creating file.\n");
		return -1;
	}

	//get the handle to standard input
	hIn = GetStdHandle(STD_INPUT_HANDLE);
	//set total written to 0
	dwTotal = 0;
	printf("Enter the text to write to the file. Enter '!' to finish.\n");
	while(TRUE){
		if((ReadFile(hIn, szBuffer, sizeof(szBuffer), &dwBytesRead, NULL))==FALSE){
			printf("Error reading from standard input.\n");
			return -2;
		}
		if(szBuffer[0]=='!'){
			printf("Finishing...\n");
			break;
		} else {
			szBuffer[dwBytesRead] = '';
		}

		//write the text to the file.
		if((WriteFile(hFile, szBuffer, strlen(szBuffer), &dwBytesWritten, NULL))==FALSE){
			printf("Error writing to the file.\n");
			return -3;
		}
		dwTotal += dwBytesWritten;
	} //end while loop

	printf("%u bytes written.\n", dwTotal);


	return 0;
}

The access mode specified in the second parameter to CreateFile() describes how we want to access the file, we can specify GENERIC_READ, GENERIC_WRITE, or a combination of the two.

The share mode is specified in the third parameter. It states whether we want the file to be shareable by other processes. If we specify 0 here, then the file is not to be shared. If we specify FILE_SHARE_READ, then other other processes may have read access to the file. If we specify FILE_SHARE_WRITE, then other processes may have write access to the file.

The fourth parameter specifies the security settings that we want applied to the file when it is created. Since we do not want any special security settings, we passed NULL for this parameter, which gave us the default settings.

The creation flags say what action to take when opening the file; here we must specify one of five values. CREATE_NEW will create a new file, and fail if the file already exists. CREATE_ALWAYS will create a new file, overwriting the file if it already exists. OPEN_EXISTING opens an existing file, and fails if the file doesn’t exist. OPEN_ALWAYS opens a file, creating it if it doesn’t exist. TRUNCATE_EXISTING opens a file and truncates its length to zero.

#include 
#include 

int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE hOne, hTwo, hThree;

	char *name = "test.txt";

	hOne = CreateFile(
		name,
		GENERIC_READ,
		0,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL
		);

	//won't work the first time we run the program
	//will work all other times
	if(hOne == INVALID_HANDLE_VALUE){
		printf("Error reading file %s with OPEN_EXISTING\n", name);
	} else {
		printf("File %s opened with OPEN_EXISTING\n", name);
		CloseHandle(hOne);
	}

	hTwo = CreateFile(
		name,
		GENERIC_WRITE,
		0, //no sharing
		NULL, //default security
		CREATE_NEW,
		FILE_ATTRIBUTE_NORMAL,
		NULL
		);

	//will work the first time we run the program
	//won't work all others
	if(hTwo == INVALID_HANDLE_VALUE){
		printf("Error creating new file %s with CREATE_NEW\n", name);
	} else {
		printf("File %s created with CREATE_NEW\n", name);
		CloseHandle(hTwo);
	}

	hThree = CreateFile(
		name,
		GENERIC_WRITE,
		0,
		NULL,
		CREATE_ALWAYS,
		FILE_ATTRIBUTE_NORMAL,
		NULL
		);

	//will always work
	if(hThree == INVALID_HANDLE_VALUE){
		printf("Error creating new file %s with CREATE_ALWAYS\n", name);
	} else {
		printf("File %s created with CREATE_ALWAYS\n", name);
	}


	return 0;
}

Note that the CloseHandle() function is used to close the file via its associated handle.

The attributes parameter sets the file flags and attributes. There are a number of file flags available. For example, the FILE_ATTRIBUTE_HIDDEN flag makes the file hidden in normal directory listings, the FILE_ATTRIBUTE_READONLY flag indicates that the file is read-only, the FILE_ATTRIBUTE_NORMAL flag indicates that the file has no other attributes set, and the FILE_ATTRIBUTE_TEMPORARY flag shows that the file is a temporary file.

The first two arguments passed to the ReadFile() function are a handle to the file to be read from and a pointer to a buffer to receive the input. The third parameter is the number of bytes to be read, and the fourth parameter is a pointer to an integer variable that will store the number of bytes that are actually read. The final parameter is used for asynchronous I/O, we will place NULL here.

The WriteFile() function is essentially the same as the ReadFile() function, except the buffer is written from, not written to. Both the ReadFile() and WriteFile() functions return TRUE if everything is copacetic and FALSE otherwise.

#include 
#include 

int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE hWrite, hRead;
	char *filename = "example.txt";
	char szBuffer[256];
	char szText[256] = "The morning sun has vanquished the horrible night.";
	DWORD dwBytesWritten, dwBytesRead;

	hWrite = CreateFile(
		filename,
		GENERIC_WRITE,
		0,
		NULL,
		CREATE_ALWAYS,
		FILE_ATTRIBUTE_NORMAL,
		NULL
		);

	if(hWrite == INVALID_HANDLE_VALUE){
		printf("Error creating file handle.\n");
		return -1;
	}

	//use strlen() and not sizeof() when writing to a file
	if(WriteFile(hWrite, szText, strlen(szText), &dwBytesWritten, NULL)){
		printf("File Written to Successfully.\n");
	} else {
		printf("Error writing to file.\n");
		return -2;
	}

	CloseHandle(hWrite);

	hRead = CreateFile(
		filename,
		GENERIC_READ,
		0,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL
		);

	if(hRead == INVALID_HANDLE_VALUE){
		printf("Error creating file handle.\n");
		return -3;
	}

	if(ReadFile(hRead, szBuffer, sizeof(szBuffer), &dwBytesRead, NULL)){
		printf("File Read from Successfully.\n");
	} else {
		printf("Error reading from file.\n");
		return -4;
	}

	szBuffer[dwBytesRead] = '';

	printf("Text: %s\n", szBuffer);

	CloseHandle(hRead);

	return 0;
}

Remember that with ReadFile() and WriteFile() we must pass a file handle, which is not the same thing as a file name.

Leave a comment