#define UNICODE
#include<iostream>
#include<string>
#include<vector>
#include<utility>
#include<exception>
#include<unordered_map>
#include <windows.h> // заголовочный файл, содержащий функции Windows API
BOOL FileExists(LPCTSTR szPath)
{
DWORD dwAttrib = GetFileAttributes(szPath);
return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
enum MenuEntry{
GetListOfDrives, ShowDriveInfo, CreateOrDeleteFolder, CreateAFile, CopyOrMoveFile, Chmod, Exit
};
typedef std::vector<std::pair<MenuEntry, std::wstring>> Menu;
typedef void (*fptr)();
typedef std::unordered_map<MenuEntry, fptr> SlotMap;
void init (Menu&);
void init (SlotMap&);
void write (const Menu&);
void ask ();
void read (size_t& answer);
void writeErrorAndWait ();
void getListOfDrives();
void showDriveInfo();
void createOrDeleteFolder();
void createFile();
void copyOrMoveFile();
void chmod();
void exitLoop();
void showTime(const FILETIME&);
FILETIME askTime();
bool isCloseRequested;
const size_t buffer_size = 100;
const unsigned long fsFlags[] = {FS_CASE_IS_PRESERVED, FS_CASE_SENSITIVE, FS_UNICODE_STORED_ON_DISK,
FS_PERSISTENT_ACLS, FS_FILE_COMPRESSION, FS_VOL_IS_COMPRESSED, FILE_NAMED_STREAMS,
FILE_SUPPORTS_ENCRYPTION, FILE_SUPPORTS_OBJECT_IDS, FILE_SUPPORTS_REPARSE_POINTS,
FILE_SUPPORTS_SPARSE_FILES, FILE_VOLUME_QUOTAS};
const std::wstring fsFlagsNames[] = {L"FS_CASE_IS_PRESERVED", L"FS_CASE_SENSITIVE", L"FS_UNICODE_STORED_ON_DISK",
L"FS_PERSISTENT_ACLS", L"FS_FILE_COMPRESSION" , L"FS_VOL_IS_COMPRESSED", L"FILE_NAMED_STREAMS",
L"FILE_SUPPORTS_ENCRYPTION", L"FILE_SUPPORTS_OBJECT_IDS", L"FILE_SUPPORTS_REPARSE_POINTS" ,
L"FILE_SUPPORTS_SPARSE_FILES" , L"FILE_VOLUME_QUOTAS" };
const unsigned long fileFlags[] = {FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_COMPRESSED, FILE_ATTRIBUTE_DIRECTORY,
FILE_ATTRIBUTE_ENCRYPTED, FS_FILE_COMPRESSION, FS_VOL_IS_COMPRESSED, FILE_NAMED_STREAMS,
FILE_SUPPORTS_ENCRYPTION, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_NORMAL,
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED, FILE_ATTRIBUTE_OFFLINE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_REPARSE_POINT,
FILE_ATTRIBUTE_SPARSE_FILE, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_TEMPORARY};
const std::wstring fileFlagsNames[] = {L"FILE_ATTRIBUTE_ARCHIVE", L"FILE_ATTRIBUTE_COMPRESSED", L"FILE_ATTRIBUTE_DIRECTORY",
L"FILE_ATTRIBUTE_ENCRYPTED", L"FS_FILE_COMPRESSION" , L"FS_VOL_IS_COMPRESSED", L"FILE_NAMED_STREAMS",
L"FILE_SUPPORTS_ENCRYPTION", L"FILE_ATTRIBUTE_HIDDEN", L"FILE_ATTRIBUTE_NORMAL" ,
L"FILE_ATTRIBUTE_NOT_CONTENT_INDEXED" , L"FILE_ATTRIBUTE_OFFLINE", L"FILE_ATTRIBUTE_READONLY",
L"FILE_ATTRIBUTE_REPARSE_POINT", L"FILE_ATTRIBUTE_SPARSE_FILE", L"FILE_ATTRIBUTE_SYSTEM" ,
L"FILE_ATTRIBUTE_TEMPORARY" };
int main(int size, char **args){
setlocale(LC_ALL, "Rus");
Menu menu;
init(menu);
SlotMap slotMap;
init(slotMap);
isCloseRequested = false;
size_t answer;
while(!isCloseRequested){
system("cls");
write(menu);
ask();
try{
read(answer);
if(answer >= menu.size()){
throw std::exception();
}
slotMap.at(menu[answer].first)();
}catch(std::exception& e){
writeErrorAndWait();
}
system("pause");
}
return 0;
}
void init (Menu& menu){
menu.clear();
menu.push_back(std::pair(MenuEntry::GetListOfDrives, L"Get list of drives"));
menu.push_back(std::pair(MenuEntry::ShowDriveInfo, L"Show info about drive"));
menu.push_back(std::pair(MenuEntry::CreateOrDeleteFolder, L"Create or delete folder"));
menu.push_back(std::pair(MenuEntry::CreateAFile, L"Create file"));
menu.push_back(std::pair(MenuEntry::CopyOrMoveFile, L"Copy or move file"));
menu.push_back(std::pair(MenuEntry::Chmod, L"Get or change list of flags of file"));
menu.push_back(std::pair(MenuEntry::Exit, L"Exit"));
}
void init (SlotMap& slotMap){
slotMap.clear();
slotMap.insert(std::pair(MenuEntry::GetListOfDrives, getListOfDrives));
slotMap.insert(std::pair(MenuEntry::ShowDriveInfo, showDriveInfo));
slotMap.insert(std::pair(MenuEntry::CreateOrDeleteFolder, createOrDeleteFolder));
slotMap.insert(std::pair(MenuEntry::CreateAFile, createFile));
slotMap.insert(std::pair(MenuEntry::CopyOrMoveFile, copyOrMoveFile));
slotMap.insert(std::pair(MenuEntry::Chmod, chmod));
slotMap.insert(std::pair(MenuEntry::Exit, exitLoop));
}
void write (const Menu& menu){
int i = 0;
for(auto& entry: menu){
std::wcout << ++i << L". \t" << entry.second << std::endl;
}
}
void ask (){
std::wcout << L"Input integer of menu index: ";
}
void read (size_t& answer){
std::wstring tmp;
std::wcin >> tmp;
answer = std::stoi(tmp);
if(answer == 0){
throw std::exception();
}
--answer;
}
void writeErrorAndWait(){
std::wcout << L"Sorry can't recognize input." << std::endl;
}
void showTime(const FILETIME& ft){
SYSTEMTIME stUTC;
FileTimeToSystemTime(&ft, &stUTC);
std::wcout << "File was created on:\t";
wprintf(L"Created on: %02d/%02d/%d %02d:%02d\n", stUTC.wDay,
stUTC.wMonth, stUTC.wYear, stUTC.wHour, stUTC.wMinute);
}
FILETIME askTime(){
FILETIME ft;
SYSTEMTIME stUTC;
short tmp;
std::wcout << L"Please, input the day:\t";
std::wcin >> tmp;
stUTC.wDay = tmp;
std::wcout << L"Please, input the month:\t";
std::wcin >> tmp;
stUTC.wMonth = tmp;
std::wcout << L"Please, input the year:\t";
std::wcin >> tmp;
stUTC.wYear = tmp;
std::wcout << L"Please, input the hour:\t";
std::wcin >> tmp;
stUTC.wHour = tmp;
std::wcout << L"Please, input the minute:\t";
std::wcin >> tmp;
stUTC.wMinute = tmp;
stUTC.wSecond = 0;
stUTC.wMilliseconds = 0;
SystemTimeToFileTime(&stUTC, &ft);
return ft;
}
std::vector<std::wstring> GetLogicalDrivePathes()
{
std::vector<std::wstring> result;
DWORD mask = GetLogicalDrives();
for( wchar_t drive = 'A'; drive <= 'Z'; ++drive )
{
if( mask & 1 )
{
std::wstring rootPath;
rootPath += drive;
rootPath += L":\\";
result.push_back( rootPath );
}
mask >>= 1;
}
return result;
}
void getListOfDrives(){
std::wcout << std:: endl << "List of logical drives (with paths):" << std:: endl;
auto drives = GetLogicalDrivePathes();
int i = 0;
for( auto& path : GetLogicalDrivePathes() )
{
std::wcout << ++i << L".\t" << path << std:: endl;
}
}
void showDriveInfo(){
std::wstring nameOfTome;
std::wcout << "Please, enter volume path (e.g. \"A:\\\"):\t";
std::wcin >> nameOfTome;
auto driveType = GetDriveType(nameOfTome.c_str());
std::wcout << "Drive type:\t";
switch(driveType){
case DRIVE_UNKNOWN:
std::wcout << L"DRIVE_UNKNOWN" << std::endl;
break;
case DRIVE_NO_ROOT_DIR:
std::wcout << L"DRIVE_NO_ROOT_DIR" << std::endl;
break;
case DRIVE_REMOVABLE:
std::wcout << L"DRIVE_REMOVABLE" << std::endl;
break;
case DRIVE_FIXED:
std::wcout << L"DRIVE_FIXED" << std::endl;
break;
case DRIVE_REMOTE:
std::wcout << L"DRIVE_REMOTE" << std::endl;
break;
case DRIVE_CDROM:
std::wcout << L"DRIVE_CDROM" << std::endl;
break;
case DRIVE_RAMDISK:
std::wcout << L"DRIVE_RAMDISK" << std::endl;
break;
}
wchar_t buffer_name[buffer_size];
wchar_t buffer_fs[buffer_size];
unsigned long serial, maximumNameLength , fsOptions;
bool isInfoValid = GetVolumeInformation(nameOfTome.c_str(), buffer_name, buffer_size, &serial, &maximumNameLength,
&fsOptions, buffer_fs , buffer_size);
if(isInfoValid){
std::wcout << L"Drive name:\t";
std::wcout << buffer_name << std::endl;
std::wcout << L"Drive file system:\t";
std::wcout << buffer_fs << std::endl;
std::wcout << L"Volume Serial Number:\t";
std::wcout << std::hex << serial << std::endl << std::dec;
std::wcout << L"Maximum name length:\t";
std::wcout << maximumNameLength << std::endl;
std::wcout << L"File system options:" << std::endl;
for(size_t i = 0; i < sizeof(fsFlags)/sizeof(unsigned long); ++i){
if(fsOptions & fsFlags[i]){
std::wcout << L"\t" << fsFlagsNames[i] << std::endl;
}
}
} else {
std::wcout << L"Can't get Volume Information" << std::endl;
}
unsigned long long accessSpace, maxSpace, freeSpace;
isInfoValid = GetDiskFreeSpaceEx(nameOfTome.c_str(), (PULARGE_INTEGER)&accessSpace,
(PULARGE_INTEGER)&maxSpace, (PULARGE_INTEGER)&freeSpace);
if(isInfoValid){
std::wcout << L"Available Free Space:\t" << static_cast<double>(accessSpace)/1024/1024/1024
<< L"Gb" << std::endl;
std::wcout << L"Total Free Space:\t" << static_cast<double>(freeSpace)/1024/1024/1024
<< L"Gb" << std::endl;
std::wcout << L"Total Space:\t" << static_cast<double>(maxSpace)/1024/1024/1024
<< L"Gb" << std::endl;
} else {
std::wcout << L"Can't get info about disk space" << std::endl;
}
}
void createOrDeleteFolder(){
size_t answer;
std::wcout << L"Choose one:\n1. Create directory\n2. Delete directory\n";
std::wcout << L"Your choise: \t";
read(answer);
if(answer >= 2){
throw std::exception();
}
std::wstring path;
std::wcout << L"Input path:\t";
std::wcin >> path;
bool success = false;
switch(answer){
case 0: //Create
success = CreateDirectory(path.c_str(), NULL); //Default security params
break;
case 1: //Delete
success = RemoveDirectory(path.c_str());
break;
}
if(success){
std::wcout << L"Success!" << std::endl;
}else{
std::wcout << L"Fail..." << std::endl;
}
}
void createFile(){
std::wstring path;
std::wcout << L"Input path: \t";
std::wcin >> path;
auto handle = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL,
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); //Default params
if(handle != INVALID_HANDLE_VALUE){
std::wcout << L"Success!" << std::endl;
}else{
std::wcout << L"Fail..." << std::endl;
}
CloseHandle(handle);
}
void copyOrMoveFile(){
size_t answer;
std::wcout << L"Choose one:\n1. Copy file\n2. Move file\n";
std::wcout << L"Your choise: \t";
read(answer);
if(answer >= 2){
throw std::exception();
}
std::wstring sourcePath;
std::wstring targetPath;
std::wcout << L"Input source path:\t";
std::wcin >> sourcePath;
std::wcout << L"Input target path:\t";
std::wcin >> targetPath;
unsigned long mustReplace = 0;
if(FileExists(targetPath.c_str())){
std::wcout << "Allow program to replace target file? 0/1: ";
std::wcin >> mustReplace;
mustReplace = mustReplace?1:0;
}
bool success = false;
switch(answer){
case 0: //Copy
success = CopyFile(sourcePath.c_str(), targetPath.c_str(), !mustReplace);
break;
case 1: //Move
success = MoveFileEx(sourcePath.c_str(), targetPath.c_str(), mustReplace);
break;
}
if(success){
std::wcout << L"Success!" << std::endl;
}else{
std::wcout << L"Fail..." << std::endl;
}
}
void chmod(){ size_t answer;
std::wcout << L"Choose one:\n1. Get attributes\n2. Set attributes\n";
std::wcout << L"Your choise: \t";
read(answer);
if(answer >= 2){
throw std::exception();
}
std::wstring path;
std::wcout << L"Input path to file:\t";
std::wcin >> path;
FILETIME ft;
bool success;
HANDLE hFile;
BY_HANDLE_FILE_INFORMATION informationStruct;
switch(answer){
case 0: //Get
hFile = CreateFile(path.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if(hFile == INVALID_HANDLE_VALUE) {
std::wcout << "Failed to open file." << std::endl;
return;
}
success = GetFileInformationByHandle(hFile, &informationStruct);
if(success){
std::wcout << L"File attributes:" << std::endl;
for(size_t i = 0; i < sizeof(fileFlags)/sizeof(unsigned long); ++i){
if(informationStruct.dwFileAttributes & fileFlags[i]){
std::wcout << L"\t" << fileFlagsNames[i] << std::endl;
}
}
std::wcout << "File was created on:\t";
showTime(informationStruct.ftCreationTime);
std::wcout << "File was accessed on:\t";
showTime(informationStruct.ftLastAccessTime);
std::wcout << "File was changed on:\t";
showTime(informationStruct.ftLastWriteTime);
std::wcout << std::hex;
std::wcout << L"The serial number of the volume that contains a file:\t" ;
std::wcout << informationStruct.dwVolumeSerialNumber << std::endl;
std::wcout << L"The number of links to this file:\t";
std::wcout << informationStruct.nNumberOfLinks << std::endl;
std::wcout << L"File index (High):\t";
std::wcout << informationStruct.nFileIndexHigh << std::endl;
std::wcout << L"File index (Low):\t";
std::wcout << informationStruct.nFileIndexLow << std::endl;
std::wcout << std::dec;
std::wcout << L"The high-order part of the file size:\t";
std::wcout << informationStruct.nFileSizeHigh << std::endl;
std::wcout << L"The low-order part of the file size:\t";
std::wcout << informationStruct.nFileSizeLow << std::endl;
}else{
std::wcout << L"Unable to get information about the file" << std::endl;
}
CloseHandle(hFile);
break;
case 1: //Set
informationStruct.dwFileAttributes = 0;
for(size_t i = 0; i < sizeof(fileFlags)/sizeof(unsigned long); ++i){
std::wcout << L"Input value of flag " << fileFlagsNames[i] << L"(0\\1):\t";
bool answer;
std::wcin >> answer;
if(answer){
informationStruct.dwFileAttributes |= fileFlags[i];
}
}
success = SetFileAttributes(path.c_str(), informationStruct.dwFileAttributes);
if(!success){
std::wcout << L"Failed to write flags" << std::endl;
}else{
std::wcout << L"Success writing flags!" << std::endl;
}
std::wcout << L"Please, input date of creation:" << std::endl;
informationStruct.ftCreationTime = askTime();
std::wcout << L"Please, input date of last acess:" << std::endl;
informationStruct.ftLastAccessTime = askTime();
std::wcout << L"Please, input date of last change:" << std::endl;
informationStruct.ftLastWriteTime = askTime();
hFile = CreateFile(path.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if(hFile == INVALID_HANDLE_VALUE) {
std::wcout << L"Failed to open file." << std::endl;
return;
}
success = SetFileTime(hFile, &informationStruct.ftCreationTime,
&informationStruct.ftLastAccessTime, &informationStruct.ftLastWriteTime);
if(!success){
std::wcout << L"Failed to write file time " << std::endl;
}else{
std::wcout << L"Success!" << std::endl;
}
CloseHandle(hFile);
break;
}
}
void exitLoop(){
std::wcout << L"Goodbye! C ya l8r :)" << std::endl;
isCloseRequested = true;
}