Copying Files Using win32 API Calls

The CopyFile() function takes source and destination filenames, plus a flag that specifies whether or not an existing file destination should be overwritten. The CopyFile() function returns a Boolean value.

#include <windows.h>


int _tmain(int argc, _TCHAR* argv[])
{
	char *filename = "testfile.txt";
	char buffer[256] = "If the fool would persist in his folly he would become wise.";
	DWORD bytesWritten;

	HANDLE hFile = CreateFile(
		filename,
		GENERIC_WRITE,
		0,
		NULL,
		CREATE_ALWAYS,
		NULL,
		NULL
		);

	if(hFile == INVALID_HANDLE_VALUE){
		printf("Error opening file handle.");
		exit(EXIT_FAILURE);
	}

	if(WriteFile(hFile, buffer, strlen(buffer), &bytesWritten, NULL)){
		printf("File written to.\n");
	} else {
		printf("File not written to.\n");
	}

	CloseHandle(hFile);

	//will fail if file already exists
	if(CopyFile(filename, "testfile_copy.txt", TRUE)){
		printf("File copied.\n");
	} else {
		printf("File not copied.\n");
	}

	//will not fail if file already exists.
	if(CopyFile(filename, "testfile_copytwo.txt", FALSE)){
		printf("File copied.\n");
	} else {
		printf("File not copied.\n");
	}

	return 0;
}

The CopyFileEx() function allows us to copy a large file and monitor the process, or even cancel it. The CopyFileEx() function takes six arguments. The first two arguments are the source file name and the destination file name. The third argument is a pointer to a progress routine; this can be set to NULL. The fourth parameter is the argument to be passed on to the callback function; we can likewise set this parameter to NULL. The fifth parameter is a Boolean value that specifies whether or not we want to cancel the copy operation. The final parameter consists of flags that tell how the file is to be copied.

#include <Windows.h>

int _tmain(int argc, _TCHAR* argv[])
{

	printf("%u (COPY_FILE_FAIL_IF_EXISTS): ", COPY_FILE_FAIL_IF_EXISTS);
	printf("The copy operation fails immediately if the taret file already exists.\n\n");

	printf("%u (COPY_FILE_COPY_SYMLINK): ", COPY_FILE_COPY_SYMLINK);
	printf("If the source file is a symbolic link, then the destination file is also a symbolic link pointing to whatever file the source symbolic link is pointing to.\n\n");

	printf("%u (COPY_FILE_NO_BUFFERING): ", COPY_FILE_NO_BUFFERING);
	printf("The copy operation is done using unbuffered I/O, bypassing system I/O cache resources.\n\n");

	printf("%u (COPY_FILE_RESTARTABLE): ", COPY_FILE_RESTARTABLE);
	printf("Progress of the copy is tracked in the target file in case the copy fails. The failed copy can then be started at a later time.");
	
	return 0;
}

The third and fourth arguments to CopyFileEx() specify the address of and the argument for a progress routine, which is a callback routine that is called whenever a portion of the file has been copied. We can place NULL here for these arguments, but instead let’s define a simple progress routine. While the progress routine is application-defined, much of the “work” involving the function’s many parameters is handled for us behind the scenes. The first thing to remember when defining a copy progress routine is that the LARGE_INTEGER type is a union, and if we are working on a 64 bit machine, and we are, we should just access the QuadPart field for each parameter of that type. The second thing to remember is that the function should return the value PROGRESS_CONTINUE in order to keep copying the file.

#include <Windows.h>

DWORD CALLBACK CopyProgressRoutine(
	LARGE_INTEGER TotalFileSize,
	LARGE_INTEGER TotalBytesTransferred,
	LARGE_INTEGER StreamSize,
	LARGE_INTEGER StreamBytesTransferred,
	DWORD dwStreamNumber,
	DWORD dwCallbackReason,
	HANDLE hSourceFile,
	HANDLE hDestinationFile,
	LPVOID lpData
	){
		int percentage = (double(TotalBytesTransferred.QuadPart) / double(TotalFileSize.QuadPart)) * 100;

		printf("%%%d copied\n", percentage);

		return PROGRESS_CONTINUE;
}


int _tmain(int argc, _TCHAR* argv[])
{
	char *filename="C:\\Program Files (x86)\\Windows NT\\Accessories\\wordpad.exe";

	bool returnVal;

	returnVal = CopyFileEx(
		filename,
		"wordpad_copy",
		(LPPROGRESS_ROUTINE)CopyProgressRoutine,
		NULL,
		NULL,
		COPY_FILE_NO_BUFFERING);

	if(returnVal){
		printf("%s copied to current directory.\n", filename);
	} else {
		printf("%s not copied to current directory.\n", filename);
		printf("Error %u.\n", GetLastError());
	}
	
	return 0;
}

Note that CALLBACK is defined as __stdcall, which is the standard calling convention for win32 system calls. With the __stdcall calling convention, the callee cleans the stack.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s