Retrieving and Changing File Attributes Program Example
An application can retrieve the file attributes by using the GetFileAttributes() or GetFileAttributesEx() function. The CreateFile() and SetFileAttributes() functions can set many of the attributes. However, applications cannot set all attributes.
The following code example uses the CopyFile() function to copy all text files (.txt) in the current directory to a new directory of read-only files. Files in the new directory are changed to read only, if necessary. The application creates the directory specified as a parameter by using the CreateDirectory() function. The directory must not exist already.
The application searches the current directory for all text files by using the FindFirstFile() and FindNextFile() functions. Each text file is copied to the \the_new_created_directory directory. After a file is copied, the GetFileAttributes() function determines whether or not a file is read only. If the file is not read only, the application changes directories to \the_new_created_directory and converts the copied file to read only by using the SetFileAttributes() function. After all text files in the current directory are copied, the application closes the search handle by using the FindClose() function.
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>
#include <strsafe.h>
// #define BUFSIZE MAX_PATH
// A prototype that receives a function name, displaying
// system error code and its respective message
void DisplayErrorBox(LPTSTR lpszFunction);
int wmain(int argc, WCHAR* argv[])
{
WIN32_FIND_DATA FileData;
HANDLE hSearch;
DWORD dwAttrs;
WCHAR szNewPath[MAX_PATH];
// WCHAR Buffer[BUFSIZE];
BOOL fFinished = FALSE;
if(argc != 2)
{
wprintf(LCopying text files in the current directory to a new directory\n);
wprintf(LUsage: %s <new dir>\n, argv[0]);
wprintf(LExample: %s C:\\testdir\n, argv[0]);
return 1;
}
// Create a new directory
if (!CreateDirectory(argv[1], NULL))
{
DisplayErrorBox(LCreateDirectory());
return 1;
}
else
wprintf(L%s directory was successfully created!\n, argv[1]);
// Start searching for text files in the current directory
hSearch = FindFirstFile(L*.txt, &FileData);
if (hSearch == INVALID_HANDLE_VALUE)
{
wprintf(LNo text files found.\n);
return 1;
}
// Copy each .TXT file to the new directory and change it to read only, if not already
while (!fFinished)
{
StringCchPrintf(szNewPath, MAX_PATH, L%s\\%s, argv[1], FileData.cFileName);
if (CopyFile(FileData.cFileName, szNewPath, FALSE))
{
dwAttrs = GetFileAttributes(FileData.cFileName);
if (dwAttrs==INVALID_FILE_ATTRIBUTES)
return 1;
if (!(dwAttrs & FILE_ATTRIBUTE_READONLY))
{
SetFileAttributes(szNewPath, dwAttrs | FILE_ATTRIBUTE_READONLY);
}
}
else
{
wprintf(LCould not copy file.\n);
return 1;
}
if (!FindNextFile(hSearch, &FileData))
{
if (GetLastError() == ERROR_NO_MORE_FILES)
{
wprintf(LCopied *.txt to %s directory\n, argv[1]);
fFinished = TRUE;
}
else
{
wprintf(LCould not find next file.\n);
return 1;
}
}
}
// Close the search handle
FindClose(hSearch);
/* Optional extra codes
// Change to the new created directory
if(!SetCurrentDirectory(argv[1]))
{
DisplayErrorBox(LSetCurrentDirectory());
return 1;
}
wprintf(LSet current directory to %s\n, argv[1]);
dwRet = GetCurrentDirectory(BUFSIZE, Buffer);
if( dwRet == 0 )
{
DisplayErrorBox(LGetCurrentDirectory());
return 1;
}
if(dwRet > BUFSIZE)
{
wprintf(LBuffer too small; need %d characters\n, dwRet);
return 1;
}
wprintf(LCurrent directory is %s\n, Buffer);
// ========= Need another loop, find first, find next =======
// Removing the read only attribute of those files
// TODO: Change all the read only file attribute to write
// so that all those file can be deleted
// Deleting all the files
if(DeleteFile(L*.txt) == 0)
DisplayErrorBox(LDeleteFile());
// ========= End loop, find first, find next =======
// Then, when the directory is empty we can remove it
if(RemoveDirectory(argv[1]) == 0)
{
DisplayErrorBox(LRemoveDirectory());
wprintf(L%s failed to be removed!\n, argv[1]);
}
*/
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 the project and to test this program you need to create a few text files under the project's Debug folder. Then, run the project. The following screenshots are sample outputs.

The following screenshot shows a sample output when the new directory already existed.

The following sample output generated when there is no text file found.
