My Training Period: zz hours. Before you begin, read some instruction here.
The Win32 C programming skills:
Obtaining and Setting File Information: Searching for One or More Files
|
The following Table lists the needed information in order to use the FindNextFile() function.
Information | Description |
The function | FindNextFile(). |
The use | Continues a file search from a previous call to the FindFirstFile() or FindFirstFileEx() function. |
The prototype | BOOL FindNextFile( HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData ); |
Example | WIN32_FIND_DATA FileData; HANDLE hSearch;
hSearch = FindFirstFile("*.txt", &FileData); FindNextFile(hSearch, &FileData); |
The parameters | hFindFile - [in] Search handle returned by a previous call to the FindFirstFile() orFindFirstFileEx() function. lpFindFileData - [out] Pointer to theWIN32_FIND_DATA structure that receives information about the found file or subdirectory. The structure can be used in subsequent calls toFindNextFile() to see the found file or directory. |
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(). If no matching files can be found, theGetLastError() function returnsERROR_NO_MORE_FILES. |
The header file | <windows.h> |
Table 9: FindNextFile() information. |
The following Table lists the needed information in order to use the FindClose() function.
Information | Description |
The function | FindClose(). |
The use | Closes a file search handle opened by theFindFirstFile(),FindFirstFileEx(), or FindFirstStreamW() function. |
The prototype | BOOL FindClose(HANDLE hFindFile); |
Example | WIN32_FIND_DATA FileData; HANDLE hSearch;
hSearch = FindFirstFile("*.txt", &FileData); FindClose(hSearch); |
The parameters | hFindFile -[in, out] File search handle. |
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: FindClose() information |
The WIN32_FIND_DATA structure describes a file found by theFindFirstFile(), FindFirstFileEx(), or FindNextFile() function.
The following is the information for the WIN32_FIND_DATA structure. Its usage is same as you have learnt before and an example how to access structure’s element will be presented in another Module.
typedef struct _WIN32_FIND_DATA {
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
DWORD dwReserved0;
DWORD dwReserved1;
TCHAR cFileName[MAX_PATH];
TCHAR cAlternateFileName[14];
} WIN32_FIND_DATA, *PWIN32_FIND_DATA;
For this structure, using the typedef, we can use WIN32_FIND_DATA or *WIN32_FIND_DATA (pointer type) as a shorter (synonym) name for the data type instead of struct _WIN32_FIND_DATA whenever we want to access the structure’s member.
It looks like a normal variable when used in programs but it is a structure. This is a normal construct in Win32 programming.
dwFileAttributes - File attributes of the file found. This member can be one or more of the following values.
Attribute | Meaning |
FILE_ATTRIBUTE_ARCHIVE | The file or directory is an archive file or directory. Applications use this attribute to mark files for backup or removal. |
FILE_ATTRIBUTE_COMPRESSED | The file or directory is compressed. For a file, this means that all of the data in the file is compressed. For a directory, this means that compression is the default for newly created files and subdirectories. |
FILE_ATTRIBUTE_DIRECTORY | The handle identifies a directory. |
FILE_ATTRIBUTE_ENCRYPTED | The file or directory is encrypted. For a file, this means that all data in the file is encrypted. For a directory, this means that encryption is the default for newly created files and subdirectories. |
FILE_ATTRIBUTE_HIDDEN | The file or directory is hidden. It is not included in an ordinary directory listing. |
FILE_ATTRIBUTE_NORMAL | The file or directory has no other attributes set. This attribute is valid only if used alone. |
FILE_ATTRIBUTE_OFFLINE | The file data is not immediately available. This attribute indicates that the file data has been physically moved to offline storage. This attribute is used by Remote Storage, the hierarchical storage management software. Applications should not arbitrarily change this attribute. |
FILE_ATTRIBUTE_READONLY | The file or directory is read-only. Applications can read the file but cannot write to it or delete it. In the case of a directory, applications cannot delete it. |
FILE_ATTRIBUTE_REPARSE_POINT | The file or directory has an associated reparse point. |
FILE_ATTRIBUTE_SPARSE_FILE | The file is a sparse file. |
FILE_ATTRIBUTE_SYSTEM | The file or directory is part of the operating system or is used exclusively by the operating system. |
FILE_ATTRIBUTE_TEMPORARY | The file is being used for temporary storage. File systems attempt to keep all of the data in memory for quicker access, rather than flushing it back to mass storage. A temporary file should be deleted by the application as soon as it is no longer needed. |
Table 11: dwFileAttributes values. |
ftCreationTime - AFILETIME structure that specifies when the file or directory was created. If the underlying file system does not support creation time, this member is zero.
ftLastAccessTime - AFILETIME structure. For a file, the structure specifies when the file was last read from or written to. For a directory, the structure specifies when the directory was created. If the underlying file system does not support last access time, this member is zero.
On FAT, the specified date for both files and directories will be correct, but the time of day will always be set to midnight.
ftLastWriteTime - AFILETIME structure. For a file, the structure specifies when the file was last written to. For a directory, the structure specifies when the directory was created. If the underlying file system does not support last write time, this member is zero.
nFileSizeHigh - High-order DWORD value of the file size, in bytes. This value is zero unless the file size is greater than MAXDWORD. The size of the file is equal to (nFileSizeHigh * (MAXDWORD+1)) + nFileSizeLow.
nFileSizeLow - Low-order DWORD value of the file size, in bytes.
dwReserved0 - If the dwFileAttributes member includes the FILE_ATTRIBUTE_REPARSE_POINT attribute, this member specifies the reparse tag. Otherwise, this value is undefined and should not be used.
dwReserved1 - Reserved for future use.
cFileName - A null-terminated string that specifies the name of the file.
cAlternateFileName - A null-terminated string that specifies an alternative name for the file. This name is in the classic 8.3 (filename.ext) file name format.
An application can retrieve the file attributes by using the GetFileAttributes() or GetFileAttributesEx() function.
The following Table lists the needed information in order to use the GetFileAttributes() function.
Information | Description |
The function | GetFileAttributes(). |
The use | Retrieves a set of FAT-style attributes for the specified file or directory. To obtain additional attribute information, use theGetFileAttributesEx() function. |
The prototype | DWORD GetFileAttributes(LPCTSTR lpFileName); |
Example | WIN32_FIND_DATA FileData;
GetFileAttributes(FileData.cFileName); |
The parameters | lpFileName - [in] Pointer to a null-terminated string that specifies the name of a file or directory. In the ANSI version of this function, the name is limited to MAX_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 contains the attributes of the specified file or directory. If the function fails, the return value isINVALID_FILE_ATTRIBUTES. To get extended error information, callGetLastError(). |
The header file | <windows.h> |
Table 12: GetFileAttributes() information. |
The CreateFile() and SetFileAttributes() functions can set many of the attributes. However, applications cannot set all attributes.
The GetFileInformationByHandle() function retrieves information about a file and stores it in aBY_HANDLE_FILE_INFORMATION structure. This information includes creation time, file size, and the file attributes.
The following program example copies all text files in the current working directory to a new directory of read-only files named newdir. Files in the new directory are changed to read only, if necessary.
The application creates the newdir directory using the CreateDirectory() function.
The application searches the current working directory for all .txt files by using the FindFirstFile() and FindNextFile() functions. In this case we have several text files under the current directory.
Each .txt file is copied to the newdir directory. After a file is copied, theGetFileAttributes() function determines whether the file is read only. If the file is not read only, the application changes directories tonewdir and converts the copied file to read only by using theSetFileAttributes() function.
After all the .txt files in the current directory have been copied, the application closes the search handle by using the FindClose() function.
The following program example uses the CreateDirectory(), FindFirstFile(), CopyFile(), GetFileAttributes(),SetFileAttributes(), FindNextFile(), lstrcpy() (string copy), lstrcat() (string cat) and FindClose() functions.
WIN32_FIND_DATA structure also used here.
#include <windows.h>
#include <stdio.h>
int main()
{
WIN32_FIND_DATA FileData;
HANDLE hSearch;
DWORD dwAttrs;
char szDirPath[] = "G:\\newdir\\";
char szNewPath[MAX_PATH];
BOOL fFinished = FALSE;
// create a new directory. If something wrong
if(!CreateDirectory(szDirPath, NULL))
{
printf("Could not create %s directory.\n", szDirPath);
// just exit
exit (0);
}
else
printf("%s directory successfully created.\n", szDirPath);
// start searching for .txt files in the current directory.
// failed when tested with a path...need to change the current working directory???
hSearch = FindFirstFile("*.txt", &FileData);
if(hSearch == INVALID_HANDLE_VALUE)
{
printf("No .txt files found lol.\n");
//just exit
exit (0);
}
// copy each .txt file to the new directory and change it to read only, if not already.
while(!fFinished)
{ // copies a string in szDirPath to szNewPath buffer...
lstrcpy(szNewPath, szDirPath);
// appends the filename to the path...
lstrcat(szNewPath, FileData.cFileName);
// in the buffer, do the file copy...
if(CopyFile(FileData.cFileName, szNewPath, FALSE))
{
printf("%s file successfully copied.\n", FileData.cFileName);
// and gets the file attribute...
dwAttrs = GetFileAttributes(FileData.cFileName);
// change to read only where applicable...
if(!(dwAttrs & FILE_ATTRIBUTE_READONLY))
SetFileAttributes(szNewPath, dwAttrs | FILE_ATTRIBUTE_READONLY);
}
else
printf("Could not copy %s file.\n", FileData.cFileName);
if(!FindNextFile(hSearch, &FileData))
{
if(GetLastError() == ERROR_NO_MORE_FILES)
{
printf("No more file lol!\n");
fFinished = TRUE;
}
else
printf("Could not find next file.\n");
}
}
// close the search handle.
FindClose(hSearch);
return 0;
}
|
The following Table lists the needed information in order to use the SearchPath() function.
Information | Description |
The function | SearchPath(). |
The use | Searches for the specified file in the specified path. |
The prototype | DWORD SearchPath( LPCTSTR lpPath, LPCTSTR lpFileName, LPCTSTR lpExtension, DWORD nBufferLength, LPTSTR lpBuffer, LPTSTR* lpFilePart ); |
Example | char PathName[50] = "C:\\ "; char fname[20] = "testfile.txt"; char lpBuffer[500]; LPSTR *lpFilePart;
SearchPath(PathName, fname, NULL, 500, lpBuffer, lpFilePart); |
The parameters | lpPath - [in] Pointer to a null-terminated string that specifies the path to be searched for the file. If this parameter is NULL, the function searches for a matching file in the following directories in the following sequence:
lpFileName - [in] Pointer to a null-terminated string that specifies the name of the file to search for. lpExtension - [in] Pointer to a null-terminated string that specifies an extension to be added to the file name when searching for the file. The first character of the file name extension must be a period (.). The extension is added only if the specified file name does not end with an extension. If a file name extension is not required or if the file name contains an extension, this parameter can beNULL. nBufferLength - [in] Size of the buffer that receives the valid path and file name, inTCHARs. lpBuffer - [out] Pointer to the buffer that receives the path and file name of the file found. lpFilePart - [out] Pointer to the variable that receives the address (withinlpBuffer) of the last component of the valid path and file name, which is the address of the character immediately following the final backslash (\) in the path. |
The return value | If the function succeeds, the value returned is the length, inTCHARs, of the string copied to the buffer, not including the terminating null character. If the return value is greater thannBufferLength, the value returned 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 13: SearchPath() information. |
The following program example uses the SearchPath() function. This program has been run at the command prompt.
#include <windows.h>
#include <stdio.h>
char lpBuffer[500];
LPSTR *lpFilePart;
int main(int argc, char *argv[ ])
{
// if not enough arguments supplied
if(argc != 3)
{
printf("Usage: %s <path> <filename.ext>\n", argv[0]);
exit (1);
}
DWORD test = SearchPath(
argv[1],
argv[2],
NULL,
500,
lpBuffer,
lpFilePart);
// if something wrong to the SearchPath()
if(!test)
{
printf("%s file not found!\n", argv[2]);
exit (1);
}
// display the result...
else
{
printf("The return value is: %d, error: %d\n", test, GetLastError());
printf("The path is %s\n", lpBuffer);
printf("The path is %p\n", lpFilePart);
}
return 0;
}
The output:
G:\vcnetprojek\win32prog\Debug>win32prog
Usage: win32prog <path> <filename.ext>
G:\vcnetprojek\win32prog\Debug>win32prog G:\
Usage: win32prog <path> <filename.ext>
G:\vcnetprojek\win32prog\Debug>win32prog G:\ testfile.txt
testfile.txt file not found!
G:\vcnetprojek\win32prog\Debug>win32prog C:\ testfile.txt
The return value is: 15, error: 0
The path is C:\testfile.txt
The path is 00000000
G:\vcnetprojek\win32prog\Debug>
The GetFileType() function retrieves the type of a file: disk, character (such as a console), pipe, or unknown.
The following Table lists the needed information in order to use the GetFileType() function.
Information | Description |
The function | GetFileType(). |
The use | Retrieves the file type of the specified file. |
The prototype | DWORD GetFileType(HANDLE hFile); |
Example | HANDLE hFile; hFile = CreateFile(...);
GetFileType(hFile); |
The parameters | hFile - [in] Handle to an open file. |
The return value | The return value is one of the following values:
|
The header file | <windows.h> |
Table 14: GetFileType() information. |
The GetBinaryType() function determines whether a file is executable, and if so, the type of executable file it is.
The following Table lists the needed information in order to use the GetBinaryType() function.
Information | Description |
The function | GetBinaryType(). |
The use | Determines whether a file is executable, and if so, what type of executable file it is. That last property determines which subsystem an executable file runs under. |
The prototype | BOOL GetBinaryType(LPCTSTR lpApplicationName, LPDWORD lpBinaryType); |
Example | DWORD lpBinaryType[100]; char fname2[30] = "c:\\windows\\NOTEPAD.EXE";
GetBinaryType(fname2, lpBinaryType); |
The parameters | lpApplicationName - [in] Pointer to a null-terminated string that contains the full path of the file whose binary type is to be determined. In the ANSI version of this function, the name is limited to MAX_PATH characters. To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\" to the path. lpBinaryType - [out] Pointer to a variable to receive information about the executable type of the file specified bylpApplicationName. The following constants are defined:
|
The return value | If the file is executable, the return value is nonzero. The function sets the variable pointed to bylpBinaryType to indicate the file's executable type. If the function is not executable, or if the function fails, the return value is zero. To get extended error information, callGetLastError(). |
The header file | <windows.h> |
Table 15: GetBinaryType() information. |
The following example uses GetFileType(), GetBinaryType() to test the file type and whether it is executable type or not.
#include <windows.h>
#include <stdio.h>
int main()
{
// handle for file
HANDLE hFile;
DWORD lpBinaryType[100];
// file and path
char fname[20] = "c:\\test.doc";
char fname2[30] = "c:\\windows\\NOTEPAD.EXE";
hFile = CreateFile(fname, // file to be opened
GENERIC_READ, // open for reading
FILE_SHARE_READ, // share for reading
NULL, // default security
OPEN_EXISTING, // open existing file
FILE_ATTRIBUTE_READONLY, // the file is read only
NULL); // no attribute template
if(hFile == INVALID_HANDLE_VALUE)
printf("Could not open %s file, error %d\n", fname, GetLastError());
printf("File's HANDLE is OK!\n");
if(GetFileType(hFile) == 0)
printf("The %s file is character type.\n", fname);
else if (GetFileType(hFile) == 1)
printf("The %s file is disk file.\n", fname);
else if (GetFileType(hFile) == 2)
printf("The %s file is socket or named pipe.\n", fname);
else if (GetFileType(hFile) == 4)
printf("The %s file is UNKNOWN type or GetFileType() failed!\n", fname);
CloseHandle(hFile);
if(GetBinaryType(fname2, lpBinaryType) != 0)
printf("The %s file is executable.\n", fname2);
else
printf("The %s is file non-executable.\n", fname2);
return 0;
}
The output:
File's HANDLE is OK!
The c:\test.doc file is disk file.
The c:\windows\NOTEPAD.EXE file is executable.
Press any key to continue
The GetFileSize() function retrieves the size of a file. Because the NTFS implementation of files allows for multiple streams within a file, any application you write that accesses files must account for the possibility that the creator of the file may include multiple streams in the file.
The following Table lists the needed information in order to use the GetFileSize() function.
Information | Description |
The function | GetFileSize(). |
The use | Retrieves the size of the specified file. The file size that can be reported by this function is limited to aDWORD value. |
The prototype | DWORD GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh); |
Example | hFile1 = CreateFile(...);
GetFileSize(hFile1, NULL); |
The parameters | hFile - [in] Handle to the file whose size is to be returned. This handle must have been created with either theGENERIC_READ or GENERIC_WRITE access right. lpFileSizeHigh - [out] Pointer to the variable where the high-order word of the file size is returned. This parameter can be NULL if the application does not require the high-order word. |
The return value | If the function succeeds, the return value is the low-order doubleword of the file size, and, if lpFileSizeHigh is non-NULL, the function puts the high-order doubleword of the file size into the variable pointed to by that parameter. If the function fails andlpFileSizeHigh is NULL, the return value isINVALID_FILE_SIZE. To get extended error information, callGetLastError(). If the function fails andlpFileSizeHigh is non-NULL, the return value isINVALID_FILE_SIZE and GetLastError() will return a value other thanNO_ERROR. |
The header file | <windows.h> |
Table 16: GetFileSize() information. |
If multiple streams are not verified for in a file, the application may underestimate the total size of the file, among other errors. The following example extracts the file type and size usingGetFileType() and GetFileSize().
#include <windows.h>
#include <stdio.h>
int main()
{
// the files' handles
HANDLE hFile, hFile1;
// filenames, change accordingly
char fname[ ] = "c:\\test.doc";
char fname1[ ] = "c:\\txtcodes\\module11.txt";
// temporary storage for file sizes
DWORD dwFileSize;
DWORD dwFileType;
// create the test file. Open it "Create Always" to overwrite any existing file...
hFile = CreateFile(fname, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
printf("hFile is NULL\n");
printf("Could not create %s\n", fname);
// return error
return 4;
}
// get the file type...
dwFileType = GetFileType(hFile);
// verify that the correct file size was written.
dwFileSize = GetFileSize(hFile, NULL);
printf("%s size is %d bytes and file type is %d\n", fname, dwFileSize, dwFileType);
CloseHandle(hFile); //close the file handle and the file itself
// opening the existing file
hFile1 = CreateFile(fname1, // file to open
GENERIC_READ, // open for reading
FILE_SHARE_READ, // share for reading
NULL, // default security
OPEN_EXISTING, // existing file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attribute template
if(hFile1 == INVALID_HANDLE_VALUE)
{
printf("Could not open %s file, error %d\n", fname1, GetLastError());
return 1;
}
dwFileType = GetFileType(hFile1);
dwFileSize = GetFileSize(hFile1, NULL);
printf("%s size is %d bytes and file type is %d\n", fname1, dwFileSize, dwFileType);
// close the file's handle and itself
CloseHandle(hFile1);
return 0;
}
The output:
c:\test.doc size is 0 bytes and file type is 1
c:\txtcodes\module11.txt size is 10518 bytes and file type is 1
Press any key to continue
The following is the previous example compiled using VC++ Express Edition with SDK on Win XP Pro SP2.
#include <windows.h>
#include <stdio.h>
int main()
{
// the files' handles
HANDLE hFile, hFile1;
// filenames, change accordingly
char *fname = "c:\\test.doc";
char *fname1 = "c:\\myfile.txt";
// temporary storage for file sizes
DWORD dwFileSize;
DWORD dwFileType;
// create the test file. Open it "Create Always" to overwrite any existing file...
hFile = CreateFile((LPCWSTR)fname, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
printf("hFile is NULL\n");
printf("Could not create %s\n", fname);
// return error
return 4;
}
// get the file type...
dwFileType = GetFileType(hFile);
// verify that the correct file size was written.
dwFileSize = GetFileSize(hFile, NULL);
printf("%s size is %d bytes and file type is %d\n", fname, dwFileSize, dwFileType);
CloseHandle(hFile); //close the file handle and the file itself
// opening the existing file
hFile1 = CreateFile((LPCWSTR)fname1, // file to open
GENERIC_READ, // open for reading
FILE_SHARE_READ, // share for reading
NULL, // default security
OPEN_EXISTING, // existing file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attribute template
if(hFile1 == INVALID_HANDLE_VALUE)
{
printf("Could not open %s file, error %d\n", fname1, GetLastError());
return 1;
}
dwFileType = GetFileType(hFile1);
dwFileSize = GetFileSize(hFile1, NULL);
printf("%s size is %d bytes and file type is %d\n", fname1, dwFileSize, dwFileType);
// close the file's handle and itself
CloseHandle(hFile1);
return 0;
}
A sample output:
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.
For Multibytes, Unicode characters and Localization please refer to Locale, wide characters & Unicode (Story) and Windows users & groups programming tutorials (Implementation).
Windows data type information is inData types used in Windows programming.
Structure, enum, union and typedef story can be foundC/C++ struct, enum, union & typedef.
Notation used in MSDN is Hungarian Notation instead of CamelCase and is discussedVC++ programming notations.