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] =
{
LTestData0 \n,
LTestData1 \n,
LTestData2 \n,
LTestData3 \n,
LTestData4 \n,
LTestData5 \n,
LTestData6 \n,
LTestData7 \n,
LTestData8 \n,
LTestData9 \n
};
int wmain(int argc, WCHAR *argv[])
{
BOOL fSuccess = FALSE;
HANDLE hFile;
LPWSTR pFileName = Ldatafile.txt;
LPWSTR pFileNameCpy = LC:\\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(LCreateFile());
// 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(LWriteFile());
return (2);
}
else
wprintf(LWriting 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(LFlushFileBuffers());
else
wprintf(LFlushing 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(LLockFileEx());
return (3);
}
else
wprintf(LLockFileEx() succeeded. %s has been locked!\n, pFileName);
wprintf(LDo 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(LUnlockFileEx());
return (4);
}
else
wprintf(LUnlockFileEx() 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(LCloseHandle());
return (5);
}
else
wprintf(LClosing the hFile handle\n);
// Just in case if you want to see the file
if(CopyFile(pFileName, pFileNameCpy, FALSE) == 0)
DisplayErrorBox(LCopyFile());
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(LDeleteFile());
return (6);
}
else
wprintf(LAll 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, LError, MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
}
Build and run the project. The following screenshot is a sample output.

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