Hart.gif (5380 bytes)Win32 System Programming

Return to Addison-Wesley Home Page  


Return to Top Page

CpMM - Memory-Mapped File Copy

This program, contributed by Andrew Savige, completes Chapter 2's collection of file copy programs and is very similar to Chapter 6's atouMM.

  1. The performance, based on several quick, informal tests, is very good for NTFS files, often producing twice the performance of cpCF, the nearest competitor (see Appendix C in the book). The performance with FAT files is about the same as for cpCF.
  2. This program illustrates some alternatives to the coding styles I elected to use in the book. (People have strong opinions on this subject! Use your own taste and judgement.) First, notice how the Win32 function calls are spaced vertically over several lines. This aids readability, at least locally, but consumes vertical space, which was scarce in the book. Secondly, notice the use of the form which I did not elect to use (many writers do not recommend it, but it does save a line):
       If ((Status = Func ()) != GOOD) ReportError ();

/* cpmm.c.  memory-mapped file implementation. Author: Andrew Savige */
/* This will have performance advantages with NTFS files */
/* and is about the same as cfCF with FAT files. */
/* cp file1 file2: Copy file1 to file2. */

#include <windows.h>
#include <stdio.h>
#include <errno.h>

int main (int argc, char *argv [])
{
  HANDLE hInFile, hOutFile;
  HANDLE hInMap, hOutMap;
  const void *pIn;
  void *pOut;
  DWORD dwSize;
  if (argc != 3) {
    printf ("Usage: cp file1 file2\n");
    return 1;
  }
  if ((hInFile=CreateFile(argv[1],
        GENERIC_READ,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        FILE_FLAG_NO_BUFFERING,
        0))==INVALID_HANDLE_VALUE) {
    printf ("Error opening input file: %s. Error Number: %d", 
          argv [1], GetLastError());
    return 2;
  }
  if ((dwSize=GetFileSize(hInFile, NULL))==0xffffffff) {
    printf ("Error getting input file size: %s. Error Number: %d",
          argv [1], GetLastError());
    return 2;
  }
  if ((hInMap=CreateFileMapping(hInFile,
        NULL,
        PAGE_READONLY,
        0,
        dwSize,
        NULL))==NULL) {
    printf ("Error creating input file mapping: %s. Error Number: %d", 
          argv [1], GetLastError());
    return 2;
  }
  if ((pIn=MapViewOfFile(
      hInMap,
      FILE_MAP_READ,
      0, 0, dwSize))==NULL) {
    printf ("Error mapping view of input file: %s. Error Number: %d", 
          argv [1], GetLastError());
    return 2;
  }
  if ((hOutFile=CreateFile(argv[2],
        GENERIC_READ|GENERIC_WRITE,
        0,
        NULL,
        CREATE_ALWAYS,
        FILE_FLAG_NO_BUFFERING,
        0))==INVALID_HANDLE_VALUE) {
    printf ("Error opening output file: %s. Error Number: %d", 
          argv [2], GetLastError());
    return 2;
  }

  if ((hOutMap=CreateFileMapping(hOutFile,
        NULL,
        PAGE_READWRITE,
        0,
        dwSize,
        NULL))==NULL) {
    printf ("Error creating output file mapping. %s: Error Number: %d", 
          argv [2], GetLastError());
    return 2;
  }
  if ((pOut=MapViewOfFile(
      hOutMap,
      FILE_MAP_WRITE,
      0, 0, dwSize))==NULL) {
    printf ("Error mapping view of output file. %s: Error Number: %d", 
          argv [2], GetLastError());
    return 2;
  }
  CopyMemory(pOut, pIn, dwSize); /* Alternative to C library memcpy */
  UnmapViewOfFile (pIn);
  UnmapViewOfFile (pOut);
  CloseHandle (hInMap);
  CloseHandle (hOutMap);
  CloseHandle (hInFile);
  CloseHandle (hOutFile);
  return 0;
}