My Training Period: xx hours. Before you begin, read someinstruction here.
The programming abilities:
Locking and Unlocking Byte Ranges in Files
|
Attempts to read from or write to a region locked by another process always fail.
The LockFileEx() function allows an application to specify either a shared lock or anexclusive lock.
An exclusive lock denies all other processes both read and write access to the specified region of the file.
A shared lock denies all processes write access to the specified region of the file, including the process that first locks the region. This can be used to create a read-only region in a file.
The application unlocks the region by using the UnlockFile() or UnlockFileEx() function. An application should unlock all locked areas before closing a file.
The following Table lists the needed information in order to use the UnlockFile() function.
Information | Description |
The function | UnlockFile(). |
The use | Unlocks a region in an open file. Unlocking a region enables other processes to access the region. For an alternate way to specify the region, use theUnlockFileEx() function. |
The prototype | BOOL UnlockFile( HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh ); |
Example | HANDLE hAppend; DWORD dwBytesRead, dwPos;
hAppend = CreateFile(...); UnlockFile(hAppend, dwPos, 0, dwBytesRead, 0); |
The parameters | hFile - [in] Handle to a file that contains a region locked with LockFile(). The file handle must have been created with either theGENERIC_READ or GENERIC_WRITE access right. dwFileOffsetLow - [in] Low-order word of the starting byte offset in the file where the locked region begins. dwFileOffsetHigh - [in] High-order word of the starting byte offset in the file where the locked region begins. nNumberOfBytesToUnlockLow - [in] Low-order word of the length of the byte range to be unlocked. nNumberOfBytesToUnlockHigh - [in] High-order word of the length of the byte range to be unlocked. |
The return value | If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error information, callGetLastError(). |
The header file | <windows.h> |
Table 7: UnlockFile() information. |
Windows stores the data in file read and write operations in system-maintained data buffers to optimize disk performance.
When an application writes to a file, the system usually buffers the data and writes the data to the disk on a regular basis.
An application can force the operating system to write the contents of these data buffers to the disk by using theFlushFileBuffers() function.
The following Table lists the needed information in order to use the FlushFileBuffers() function.
Information | Description |
The function | FlushFileBuffers(). |
The use | Flushes the buffers of the specified file and causes all buffered data to be written to the file. |
The prototype | BOOL FlushFileBuffers(HANDLE hFile); |
Example | HANDLE hFile;
hFile = CreateFile(...); FlushFileBuffers(HANDLE hFile); |
The parameters | hFile - [in] Handle to an open file. The file handle must have the GENERIC_WRITE access right. IfhFile is a handle to a communications device, the function only flushes the transmit buffer. IfhFile is a handle to the server end of a named pipe, the function does not return until the client has read all buffered data from the pipe. |
The return value | If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error information, callGetLastError(). The function fails ifhFile is a handle to console output. That is because console output is not buffered. The function returns FALSE, andGetLastError() returns ERROR_INVALID_HANDLE. |
The header file | <windows.h> |
Table 8: FlushFileBuffers() information. |
Alternatively, an application can specify that write operations are to bypass the data buffer and write directly to the disk by setting theFILE_FLAG_NO_BUFFERING flag when the file is created or opened using theCreateFile() function.
If there is data in the internal buffer when the file is closed, the operating system does not automatically write the contents of the buffer to the disk before closing the file.
If the application does not force the operating system to write the buffer to disk before closing the file, the caching algorithm determines when the buffer is written.
Accessing a data buffer while a read or write operation is using it may corruption the buffer. Applications must not read from, write to, reallocate, or free the data buffer that a read or write operation is using until the operation completes.
The following program example appends one file to the end of another file. The application opens two files by usingCreateFile(): The testfile.txt is opened for reading, and testfiletwo.txt is opened for writing.
Then the application appends the contents of testfile.txt to the end of testfiletwo.txt by reading and writing 4K blocks by usingReadFile() and WriteFile().
Before writing to the second file, the application sets the second file's pointer to the end of the file by usingSetFilePointer() and locks the area to be written by usingLockFile().
This prevents another process from accessing the area while the write is in progress. After each write operation,UnlockFile() unlocks the locked area.
#include <windows.h>
#include <stdio.h>
int main()
{
HANDLE hFile;
HANDLE hAppend;
DWORD dwBytesRead, dwBytesWritten, dwPos;
char fname[30] = "c:\\testfile.txt";
char fname2[30] = "c:\\testfiletwo.txt";
char buff[4096];
// open the existing file.
hFile = CreateFile(fname, //open testfile.txt
GENERIC_READ, //open for reading
0, //do not share
NULL, //default security
OPEN_EXISTING, //existing file only
FILE_ATTRIBUTE_NORMAL, //normal file
NULL); //no attribute template
if(hFile == INVALID_HANDLE_VALUE)
printf("Could not open %s lol!.\n", fname);
else
printf("%s opened successfully.\n", fname);
// open the existing file, or if the file does not exist, create a new file.
hAppend = CreateFile(fname2, //open testfiletwo.txt
GENERIC_WRITE, //open for writing
0, //do not share
NULL, //default security
OPEN_ALWAYS, //open or create
FILE_ATTRIBUTE_NORMAL, //normal file
NULL); //no attribute template
if(hAppend == INVALID_HANDLE_VALUE)
printf("Could not open %s lol!.\n", fname2);
else
{
printf("%s opened/created successfully.\n", fname2);
printf("\nAppending %s\'s content to %s\'s content\n", fname, fname2);
printf("Check the %s content lol!\n\n", fname2);
}
// append the first file to the end of the second file. Lock the second file to prevent another process from
// accessing it while writing to it. Unlock the file when writing is finished.
do
{
if(ReadFile(hFile, buff, 4096, &dwBytesRead, NULL))
{
dwPos = SetFilePointer(hAppend, 0, NULL, FILE_END);
if(LockFile(hAppend, dwPos, 0, dwBytesRead, 0) != 0)
printf("Locking %s...\n", fname2);
WriteFile(hAppend, buff, dwBytesRead, &dwBytesWritten, NULL);
if(UnlockFile(hAppend, dwPos, 0, dwBytesRead, 0) != 0)
printf("Unlocking %s...\n", fname2);
}
} while (dwBytesRead == 4096);
// close both files.
if(CloseHandle(hFile) != 0)
printf("\nFile handle closed successfully!\n");
if(CloseHandle(hAppend) != 0)
printf("File's append handle closed successfully!\n");
return 0;
}
The output:
c:\testfile.txt opened successfully.
c:\testfiletwo.txt opened/created successfully.
Appending c:\testfile.txt's content to c:\testfiletwo.txt's content
Check the c:\testfiletwo.txt content lol!
Locking c:\testfiletwo.txt...
Unlocking c:\testfiletwo.txt...
Locking c:\testfiletwo.txt...
Unlocking c:\testfiletwo.txt...
Locking c:\testfiletwo.txt...
Unlocking c:\testfiletwo.txt...
Locking c:\testfiletwo.txt...
Unlocking c:\testfiletwo.txt...
Locking c:\testfiletwo.txt...
Unlocking c:\testfiletwo.txt...
File handle closed successfully!
File's append handle closed successfully!
Press any key to continue
|
The Encrypted File System, or EFS, was introduced in version 5 of NTFS to provide an additional level of security for files and directories.
It provides cryptographic protection of individual files on NTFS volumes using a public-key system. Typically, the access control to file and directory objects provided by the Windows security model is sufficient to protect unauthorized access to sensitive information.
However, if a laptop containing sensitive data is lost or stolen, the security protection of that data may be compromised. Encrypting the files increases security in this scenario.
To determine whether a file system supports file encryption for files and directories, call the GetVolumeInformation() function and examine the FS_FILE_ENCRYPTION bit flag. Note that the following items cannot be encrypted:
Compressed files.
System files.
System directories.
Root directories.
Sparse files may be encrypted.
NTFS volumes support file compression on an individual file basis. The file compression algorithm used by NTFS is Lempel-Ziv compression.
This is a lossless compression algorithm, which means that no data is lost when compressing and decompressing the file, as opposed to lossy compression algorithms such as JPEG, where some data is lost each time data compression and decompression occur.
Data compression reduces the size of a file by minimizing redundant data. In a text file, redundant data can be frequently occurring characters, such as the space character, or common vowels, such as the letters e anda; it can also be frequently occurring character strings.
Data compression creates a compressed version of a file by minimizing this redundant data.
Each type of data-compression algorithm minimizes redundant data in a unique manner. For example, the Huffman encoding algorithm assigns a code to characters in a file based on how frequently those characters occur.
Another compression algorithm, called run-length encoding, generates a two-part value for repeated characters: the first part specifies the number of times the character is repeated, and the second part identifies the character.
Another compression algorithm, known as the Lempel-Ziv algorithm, converts variable-length strings into fixed-length codes that consume less space than the original strings.
Typically, an application calls functions in LzExpand.dll to decompress data.
Applications can call the functions in LzExpand.dll to decompress files that have been compressed by the use of the Lempel-Ziv compression algorithm. The functions can also process uncompressed files without attempting to decompress them.
You can use the functions in LzExpand.dll to decompress single or multiple files. You can also use them to decompress compressed files a portion at a time.
A file in which much of the data is zeros is said to contain a sparse data set. Files like these are typically very large.
For example, a file containing image data to be processed or a matrix within a high-speed database. The problem with files containing sparse data sets is that the majority of the file does not contain useful data and, because of this, they are an inefficient use of disk space.
The file compression introduced in version 3.51 of NTFS is a partial solution to the problem. All data in the file that is not explicitly written is explicitly set to zero.
File compression compacts these ranges of zeros. However, a drawback of file compression is that access time may increase due to data compression and decompression.
Support for sparse files was introduced in NTFS as another way to make the disk space usage more efficient.
When the sparse file functionality is enabled, the system does not allocate hard drive space to a file except in regions where it contains nonzero data. When a write operation is attempted where a large amount of the data in the buffer is zeros, the zeros are not written to the file.
Instead, the file system creates an internal list containing the locations of the zeros in the file, and this list is consulted during all read operations.
When a read operation is performed in areas of the file where zeros were located, the file system returns the appropriate number of zeros in the buffer allocated for the read operation. In this way, maintenance of the sparse file is transparent to all processes that access it.
The default data value of a sparse file is zero; however, it can be set to other values.
NTFS provides the ability to create a system representation of a file or directory in a location in the directory structure that is different from the file or directory object that is being linked to.
This process is calling linking. There are two types of links supported in NTFS: hard links and junctions.
NTFS also provides the distributed link tracking service, which automatically tracks links as they are moved.
The following Table lists the information needed in order to use the CreateDirectory() function.
Information | Description |
The function | CreateDirectory(). |
The use | Creates a new directory. If the underlying file system supports security on files and directories, the function applies a specified security descriptor to the new directory. |
The prototype | BOOL CreateDirectory( LPCTSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes); |
Example | char szDirPath[20] = "c:\\testdir"; CreateDirectory(szDirPath, NULL); |
The parameters | lpPathName - [in] Pointer to a null-terminated string that specifies the path of the directory to be created. There is a default string size limit for paths of 248 characters. This limit is related to how theCreateDirectory() function parses paths. To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\" to the path. lpSecurityAttributes - [in] Pointer to aSECURITY_ATTRIBUTES structure. ThelpSecurityDescriptor member of the structure specifies a security descriptor for the new directory. IflpSecurityAttributes is NULL, the directory gets a default security descriptor. The ACLs in the default security descriptor for a directory are inherited from its parent directory. The target file system must support security on files and directories for this parameter to have an effect. |
The return value | If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error information, call GetLastError(). Possible errors include the following:
|
The header file | <windows.h> |
Table 9: CreateDirectory() information |
And the following is an information for RemoveDirectory() function.
Information | Description |
The function | RemoveDirectory(). |
The use | Deletes an existing empty directory. |
The prototype | BOOL RemoveDirectory(LPCTSTR lpPathName); |
Example | char szDirPath[20] = "c:\\testdir";
RemoveDirectory(szDirPath); |
The parameters | lpPathName - [in] Pointer to a null-terminated string that specifies the path of the directory to be removed. The path must specify an empty directory, and the calling process must have delete access to the directory. In the ANSI version of this function, the name is limited toMAX_PATH characters. To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\" to the path. |
The return value | If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error information, callGetLastError(). |
The header file | <windows.h> |
Table 10: RemoveDirectory() information |
The RemoveDirectory() function marks a directory for deletion on close. Therefore, the directory is not removed until the last handle to the directory is closed.
To recursively delete the files in a directory, use the SHFileOperation() function.
The following program example uses CreateDirectory(), CreateFile(), CloseHandle(), DeleteFile() andRemoveDirectory() functions.
#include <windows.h>
#include <stdio.h>
int main()
{
char szDirPath[20] = "c:\\testdir";
HANDLE hFile;
char fname[50] = "c:\\testdir\\testfile.txt";
// create a new directory.
if(!CreateDirectory(szDirPath, NULL))
printf("Couldn't create %s directory.\n", szDirPath);
else
printf("%s directory successfully created.\n", szDirPath);
// create a file
hFile = CreateFile(fname, //file to be opened
GENERIC_READ, //open for writing
FILE_SHARE_READ, //share for writing
NULL, //default security
CREATE_ALWAYS, //create new file only
FILE_ATTRIBUTE_ARCHIVE | SECURITY_IMPERSONATION, //archive and impersonate client
NULL); //no attribute template
// check the handle, then open...
if(hFile == INVALID_HANDLE_VALUE)
printf("Could not open %s file (error %d)\n", fname, GetLastError());
else
{
printf("%s file HANDLE is OK!\n", fname);
printf("%s opened successfully!\n", fname);
}
// close the handle...
if(CloseHandle(hFile) != 0)
printf("CloseHandle() for %s file succeeded!\n", fname);
if(DeleteFile(fname) != 0)
printf("%s file successfully deleted!\n", fname);
// delete the directory...
if(RemoveDirectory(szDirPath) != 0)
printf("%s directory successfully deleted.\n", szDirPath);
return 0;
}
The output:
c:\testdir directory successfully created.
c:\testdir\testfile.txt file HANDLE is OK!
c:\testdir\testfile.txt opened successfully!
CloseHandle() for c:\testdir\testfile.txt file succeeded!
c:\testdir\testfile.txt file successfully deleted!
c:\testdir directory successfully deleted.
Press any key to continue
A sample output using VC++ 2005.
The following Table lists the information needed in order to use the GetCurrentDirectory() function.
Information | Description |
The function | GetCurrentDirectory(). |
The use | Retrieves the current directory for the current process. |
The prototype | DWORD GetCurrentDirectory( DWORD nBufferLength, LPTSTR lpBuffer); |
Example | #define BUFFER_SIZE 200 TCHAR infoBuf[BUFFER_SIZE];
GetCurrentDirectory(BUFFER_SIZE, infoBuf); |
The parameters | nBufferLength - [in] Length of the buffer for the current directory string, in TCHARs. The buffer length must include room for a terminating null character. lpBuffer - [out] Pointer to the buffer that receives the current directory string. This null-terminated string specifies the absolute path to the current directory. |
The return value | If the function succeeds, the return value specifies the number of characters written to the buffer, not including the terminating null character. If the function fails, the return value is zero. To get extended error information, call GetLastError(). If the buffer pointed to bylpBuffer is not large enough, the return value specifies the required size of the buffer, in characters, including the null- terminating character. |
The header file | <windows.h> |
Table 11: GetCurrentDirectory() information. |
The following Table lists the information needed in order to use the SetCurrentDirectory() function.
Information | Description |
The function | SetCurrentDirectory(). |
The use | Changes the current directory for the current process. Each process has a single current directory made up of two parts:
|
The prototype | BOOL SetCurrentDirectory(LPCTSTR lpPathName); |
Example | TCHAR lpPathName[200] = "D:\\Program Files\\Microsoft sql server"; SetCurrentDirectory(lpPathName); |
The parameters | lpPathName - [in] Pointer to a null-terminated string that specifies the path to the new current directory. This parameter may be a relative path or a full path. In either case, the full path of the specified directory is calculated and stored as the current directory. The string must not exceedMAX_PATH characters, including the terminating null character. The final character before the null character must be a backslash ('\'). If you do not specify the backslash, it will be added for you. Therefore you can specifyMAX_PATH-2 characters for the path orMAX_PATH-1 characters for the path if you include the trailing backslash. |
The return value | If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error information, callGetLastError(). |
The header file | <windows.h> |
Table 12: SetCurrentDirectory() information. |
Applications should store code in the Program Files folder and persistent data in the Application Data folder in the user's profile.
Applications should not create files in the system directory. If the user is running a shared version of the operating system, the application does not have write access to the system directory.
This function is provided primarily for compatibility.
Instead, you should use the CSIDL values in conjunction with one of four Shell functions,SHGetFolderLocation(), SHGetFolderPath(), SHGetSpecialFolderLocation(), and SHGetSpecialFolderPath(), to retrieve a special folder's path or pointer to an item identifier list (PIDL).
CSIDL values provide a unique system-independent way to identify special folders used frequently by applications, but which may not have the same name or location on any given system. For example, the system folder may be "C:\Windows" (Windows Xp) on one machine and "C:\Winnt" (Windows 2000) on another.
The following Table lists the information needed in order to use the GetSystemDirectory() function.
Information | Description |
The function | GetSystemDirectory(). |
The use | Retrieves the path of the system directory. The system directory contains system such files such as dynamic-link libraries, drivers, and font files. |
The prototype | UINT GetSystemDirectory(LPTSTR lpBuffer, UINT uSize); |
Example | #define BUFFER_SIZE 200 TCHAR infoBuf[BUFFER_SIZE];
GetSystemDirectory(infoBuf, BUFFER_SIZE); |
The parameters | lpBuffer - [out] Pointer to the buffer to receive the null-terminated string containing the path. This path does not end with a backslash unless the system directory is the root directory. For example, if the system directory is namedWindows\System on drive C, the path of the system directory retrieved by this function is C:\Windows\System. uSize - [in] Maximum size of the buffer, inTCHARs. This value should be set toMAX_PATH. |
The return value | If the function succeeds, the return value is the length, inTCHARs, of the string copied to the buffer, not including the terminating null character. If the length is greater than the size of the buffer, the return value is the size of the buffer required to hold the path, including the terminating null character. If the function fails, the return value is zero. |
The header file | <windows.h> |
Table 13: GetSystemDirectory() information |
The Windows directory is the directory where an application should store initialization and help files.
If the user is running a shared version of the system, the Windows directory is guaranteed to be private for each user.
If an application creates other files that it wants to store on a per-user basis, it should place them in the directory specified by theHOMEPATH environment variable.
This directory will be different for each user, if so specified by an administrator, through the User Manager administrative tool.
HOMEPATH always specifies either the user's home directory, which is guaranteed to be private for each user, or a default directory (for example,C:\USERS\DEFAULT) where the user will have all access.
The following Table lists the information needed in order to use the GetWindowsDirectory() function.
Information | Description |
The function | GetWindowsDirectory(). |
The use | Retrieves the path of the Windows directory. The Windows directory contains such files as applications, initialization files, and help files. |
The prototype | UINT GetWindowsDirectory(LPTSTR lpBuffer, UINT uSize); |
Example | #define BUFFER_SIZE 200 TCHAR infoBuf[BUFFER_SIZE];
GetWindowsDirectory(infoBuf, BUFFER_SIZE); |
The parameters | lpBuffer - [out] Pointer to the buffer to receive the null-terminated string containing the path. This path does not end with a backslash unless the Windows directory is the root directory. For example, if the Windows directory is namedWindows on drive C, the path of the Windows directory retrieved by this function is C:\Windows. If the system was installed in the root directory of drive C, the path retrieved isC:\. uSize - [in] Maximum size of the buffer specified by the lpBuffer parameter, in TCHARs. This value should be set toMAX_PATH. |
The return value | If the function succeeds, the return value is the length of the string copied to the buffer, in TCHARs, not including the terminating null character. If the length is greater than the size of the buffer, the return value is the size of the buffer required to hold the path. If the function fails, the return value is zero. To get extended error information, callGetLastError(). |
The header file | <windows.h> |
Table 14: GetWindowsDirectory() information. |
The following program example uses GetCurrentDirectory(), SetCurrentDirectory(), GetWindowsDirectory() and GetSystemDirectory() functions.
#include <windows.h>
#include <stdio.h>
#define BUFFER_SIZE 200
int main()
{
TCHAR infoBuf[BUFFER_SIZE];
// Change accordingly to other path of your machine
TCHAR lpPathName[200] = "D:\\mydvd\\Adobe Acrobat 3D 8.1";
// get the current working directory
if(!GetCurrentDirectory(BUFFER_SIZE, infoBuf))
printf("GetCurrentDirectory() failed!\n");
printf("Your current directory is: %s\n", infoBuf);
printf("Changing directory...\n");
// set to current working directory
if(!SetCurrentDirectory(lpPathName))
printf("SetCurrentDirectory() failed!\n");
// do some verification...
if(!GetCurrentDirectory(BUFFER_SIZE, infoBuf))
printf("GetCurrentDirectory() failed!\n");
printf("Your current directory is: %s\n", infoBuf);
// get and display the Windows directory.
if(!GetWindowsDirectory(infoBuf, BUFFER_SIZE))
printf("GetWindowsDirectory() failed!\n");
printf("Your Windows directory is: %s\n", infoBuf);
// get and display the system directory.
if(!GetSystemDirectory(infoBuf, BUFFER_SIZE))
printf("GetSystemDirectory() failed!\n");
printf("Your system directory is: %s\n", infoBuf);
return 0;
}
The output:
Your current directory is: g:\vcnetprojek\win32prog
Changing directory...
Your current directory is: D:\Program Files\Microsoft sql server
Your Windows directory is: C:\WINDOWS
Your system directory is: C:\WINDOWS\system32
Press any key to continue
Check the best selling C, C++ and Windows books at Amazon.com.
Microsoft Visual C++, online MSDN.
ReactOS - Windows binary compatible OS - C/C++ source code repository, Doxygen.
Notation used in MSDN is Hungarian Notation instead of CamelCase and is discussedVC++ programming notations.
Windows data type information is inData types used in Windows programming.
For Multi bytes, Unicode characters and Localization please refer to Locale, wide characters & Unicode (Story) and Windows users & groups programming tutorials (Implementation).
Structure, enum, union and typedef story can be foundC/C++ struct, enum, union & typedef.