The Windows File Management 21

 

 

 

 

 

Locking and Unlocking Byte Ranges in Files Program Example

 

Although the system allows more than one application to open a file and write to it, applications must not write over each other's work. An application can prevent this problem by temporarily locking a byte range in a file. The LockFile() and LockFileEx() functions lock a specified range of bytes in a file. The range may extend beyond the current end of the file. Locking part of a file gives the threads of the locking processes exclusive access to the specified byte range by using the specified file handle. Attempts to access a byte range that is locked by another process always fail. If the locking process attempts to access a locked byte range through a second file handle, the attempt fails. The LockFileEx() function allows an application to specify one of two types of locks. An exclusive lock denies all other processes both read and write access to the specified byte range of a file. A shared lock denies all processes write access to the specified byte range of a file, including the process that first locks the byte range. This can be used to create a read-only byte range in a file. The application unlocks the byte range by using the UnlockFile() or UnlockFileEx() function. An application should unlock all locked areas before closing a file. The following program example shows you how to use LockFileEx(). It creates a file, writes some data to it, and then locks a section in the middle. This example does not change the data once the file is locked.

Create a new empty Win32 console application project. Give a suitable project name and change the project location if needed.

Then, add the source file and give it a suitable name.

Next, add the following source code.

 

#include <windows.h>

#include <stdio.h>

// A safer version for string manipulation

#include <strsafe.h>

 

#define NUMWRITES 10

#define TESTSTRLEN 12

 

// A prototype that receives a function name, displaying

// system error code and its respective message

void DisplayErrorBox(LPTSTR lpszFunction);

 

// 2D  arrays

const WCHAR TestData[NUMWRITES][TESTSTRLEN] =

{

    L"TestData0 \n",

    L"TestData1 \n",

    L"TestData2 \n",

    L"TestData3 \n",

    L"TestData4 \n",

    L"TestData5 \n",

    L"TestData6 \n",

    L"TestData7 \n",

    L"TestData8 \n",

    L"TestData9 \n"

};

 

int wmain(int argc, WCHAR *argv[])

{

    BOOL fSuccess = FALSE;

      HANDLE hFile;

      LPWSTR pFileName = L"datafile.txt";

      LPWSTR pFileNameCpy = L"C:\\datafilecopy.txt";

      DWORD dwNumBytesWritten;

 

    // Create the file, open for both read and write.

    hFile = CreateFile(pFileName,

                       GENERIC_READ | GENERIC_WRITE,

                       0,          // open with exclusive access

                       NULL,       // no security attributes

                       CREATE_NEW, // creating a new temp file

                       0,          // not overlapped index/O

                       NULL);

   

    if (hFile == INVALID_HANDLE_VALUE)

    {

        // Handle the error.

        DisplayErrorBox(L"CreateFile()");

        // Non-zero is error

        return (1);

    }

      else

            wprintf(L"%s was successfully created!\n", pFileName);

 

    // Write some data to the file.

    dwNumBytesWritten = 0;

 

    for (int i=0; i<NUMWRITES; i++)

    {

        fSuccess = WriteFile(hFile,

                             TestData[i],

                             TESTSTRLEN,

                             &dwNumBytesWritten,

                             NULL);  // sync operation.

        if (!fSuccess)

        {

           // Handle the error.

           DisplayErrorBox(L"WriteFile()");

           return (2);

        }

        else

           wprintf(L"Writing data to %s file\n", pFileName);

    }

 

      // Flushes the buffers of a specified file and causes

      // all buffered data to be written to a file.

    if(FlushFileBuffers(hFile) == 0)

            DisplayErrorBox(L"FlushFileBuffers()");

    else

            wprintf(L"Flushing buffer, buffered data written to %s file\n", pFileName);

 

    // Lock the 4th write-section.  First, set up the Overlapped structure

    // with the file offset required by LockFileEx, three lines in to the file.

    OVERLAPPED sOverlapped;

    sOverlapped.Offset = TESTSTRLEN * 3;

    sOverlapped.OffsetHigh = 0;

 

    // Actually lock the file.  Specify exclusive access, and fail

    // immediately if the lock cannot be obtained.

    fSuccess = LockFileEx(hFile,         // exclusive access,

                          LOCKFILE_EXCLUSIVE_LOCK |

                          LOCKFILE_FAIL_IMMEDIATELY,

                          0,             // reserved, must be zero

                          TESTSTRLEN,    // number of bytes to lock

                          0,

                          &sOverlapped); // contains the file offset

    if (!fSuccess)

    {

       // Handle the error.

       DisplayErrorBox(L"LockFileEx()");

       return (3);

    }

    else

            wprintf(L"LockFileEx() succeeded. %s has been locked!\n", pFileName);

 

    wprintf(L"Do my job to the locked file\n so no \'object\' will interrupt me...\n");

    /////////////////////////////////////////////////////////////////

    // Add code that does something interesting to locked section,  /

    // which should be line 4                                       /

    /////////////////////////////////////////////////////////////////

 

    // Unlock the file.

    fSuccess = UnlockFileEx(hFile,

                            0,             // reserved, must be zero

                            TESTSTRLEN,    // num. of bytes to unlock

                            0,

                            &sOverlapped); // contains the file offset

    if (!fSuccess)

    {

       // Handle the error.

       DisplayErrorBox(L"UnlockFileEx()");

       return (4);

    }

    else

            wprintf(L"UnlockFileEx() succeeded.\n %s has been unlocked, ready for other \'objects\'\n", pFileName);

 

    // Clean up handles, memory, and the created file.

    fSuccess = CloseHandle(hFile);

 

    if (!fSuccess)

    {

       // Handle the error.

       DisplayErrorBox(L"CloseHandle()");

       return (5);

    }

      else

            wprintf(L"Closing the hFile handle\n");

 

      // Just in case if you want to see the file

      if(CopyFile(pFileName, pFileNameCpy, FALSE) == 0)

            DisplayErrorBox(L"CopyFile()");

      else

            wprintf(L"%s was successfully copied to %s\n", pFileName, pFileNameCpy);

 

    // Finally delete the original file

    fSuccess = DeleteFile(pFileName);

 

    if (!fSuccess)

    {

       // Handle the error.

       DisplayErrorBox(L"DeleteFile()");

       return (6);

    }

      else

            wprintf(L"All done. %s was successfully deleted\n", pFileName);

    return (0);

}

 

void DisplayErrorBox(LPTSTR lpszFunction)

{

    // Retrieve the system error message for the last-error code

    LPVOID lpMsgBuf;

    LPVOID lpDisplayBuf;

    DWORD dw = GetLastError();

 

    FormatMessage(

        FORMAT_MESSAGE_ALLOCATE_BUFFER |

        FORMAT_MESSAGE_FROM_SYSTEM |

        FORMAT_MESSAGE_IGNORE_INSERTS,

        NULL,

        dw,

        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),

        (LPTSTR) &lpMsgBuf,

        0, NULL );

 

    // Display the error message and clean up

    lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,  (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(WCHAR));

    StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(WCHAR),  L"%s failed with error %d: %s", lpszFunction, dw, lpMsgBuf);

    MessageBox(NULL, (LPCTSTR)lpDisplayBuf, L"Error", MB_OK);

 

    LocalFree(lpMsgBuf);

    LocalFree(lpDisplayBuf);

}

 

Build and run the project. The following screenshot is a sample output.

 

Locking and Unlocking Byte Ranges in Files Program Example: A sample console program output in action

 

The following is a copy of the datafilecopy.txt text file's content.

 

Locking and Unlocking Byte Ranges in Files Program Example: a copy of the datafilecopy.txt text file's content

 

 

 

 

< Windows Files 20 | Win32 Programming | Win32 File Index | Windows Files 22 >