Index: base/applications/cacls/cacls.c =================================================================== --- base/applications/cacls/cacls.c (revision 57871) +++ base/applications/cacls/cacls.c (working copy) @@ -19,6 +19,11 @@ #include +/* command line options */ +BOOL OptionT = FALSE, OptionE = FALSE, OptionC = FALSE; +BOOL OptionG = FALSE, OptionR = FALSE, OptionP = FALSE, OptionD = FALSE; +LPCTSTR GUser, GPerm, RUser, PUser, PPerm, DUser; + static GENERIC_MAPPING FileGenericMapping = { FILE_GENERIC_READ, @@ -512,93 +517,499 @@ return Ret; } +/* add a backslash at end to a path string if necessary */ +static VOID +AddBackslash(LPTSTR FilePath) +{ + INT len = lstrlen(FilePath); + LPTSTR pch = CharPrev(FilePath, FilePath + len); + if (*pch != _T('\\')) + lstrcat(pch, _T("\\")); +} -int -__cdecl -_tmain(int argc, const TCHAR *argv[]) +static BOOL +GetPathOfFile(LPTSTR FilePath, LPCTSTR pszFiles) { - if (argc < 2) + TCHAR FullPath[MAX_PATH]; + LPTSTR pch; + DWORD attrs; + + lstrcpyn(FilePath, pszFiles, MAX_PATH); + pch = _tcsrchr(FilePath, _T('\\')); + if (pch != NULL) { - PrintHelp(); - return 1; + *pch = 0; + if (!GetFullPathName(FilePath, MAX_PATH, FullPath, NULL)) + { + PrintErrorMessage(GetLastError()); + return FALSE; + } + lstrcpyn(FilePath, FullPath, MAX_PATH); + + attrs = GetFileAttributes(FilePath); + if (attrs == 0xFFFFFFFF || !(attrs & FILE_ATTRIBUTE_DIRECTORY)) + { + PrintErrorMessage(ERROR_DIRECTORY); + return FALSE; + } } else + GetCurrentDirectory(MAX_PATH, FilePath); + + AddBackslash(FilePath); + return TRUE; +} + +static BOOL +PrintDaclsOfFiles(LPCTSTR pszFiles) +{ + TCHAR FilePath[MAX_PATH]; + WIN32_FIND_DATA FindData; + HANDLE hFind; + DWORD LastError; + + /* + * get the file path + */ + if (!GetPathOfFile(FilePath, pszFiles)) + return FALSE; + + /* + * search for the files + */ + hFind = FindFirstFile(pszFiles, &FindData); + if (hFind == INVALID_HANDLE_VALUE) + return FALSE; + + do { - TCHAR FullPath[MAX_PATH + 1]; - TCHAR *FilePart = NULL; - WIN32_FIND_DATA FindData; - HANDLE hFind; - DWORD LastError; + if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + continue; - if (argc > 2) + if (!PrintFileDacl(FilePath, FindData.cFileName)) { - /* FIXME - parse arguments */ + LastError = GetLastError(); + if (LastError == ERROR_ACCESS_DENIED) + { + PrintErrorMessage(LastError); + if (!OptionC) + { + FindClose(hFind); + return FALSE; + } + } + else + break; } + else + _tprintf(_T("\n")); + } while(FindNextFile(hFind, &FindData)); + LastError = GetLastError(); + FindClose(hFind); - /* get the full path of where we're searching in */ - if (GetFullPathName(argv[1], - sizeof(FullPath) / sizeof(FullPath[0]), - FullPath, - &FilePart) != 0) + if (LastError != ERROR_NO_MORE_FILES) + { + PrintErrorMessage(LastError); + return FALSE; + } + + return TRUE; +} + +static BOOL +GrantUserAccessRights(LPCTSTR FilePath, LPCTSTR File, LPCTSTR User, TCHAR Perm) +{ + /* TODO & FIXME */ + switch(Perm) + { + case _T('R'): // Read + break; + case _T('W'): // Write + break; + case _T('C'): // Change (write) + break; + case _T('F'): // Full control + break; + default: + break; + } + return FALSE; +} + +static BOOL +ReplaceUserAccessRights( + LPCTSTR FilePath, + LPCTSTR File, + LPCTSTR User, + TCHAR Perm) +{ + /* TODO & FIXME */ + switch(Perm) + { + case _T('N'): // None + break; + case _T('R'): // Read + break; + case _T('W'): // Write + break; + case _T('C'): // Change (write) + break; + case _T('F'): // Full control + break; + default: + break; + } + return FALSE; +} + +static BOOL +EditUserAccessRights( + LPCTSTR FilePath, + LPCTSTR File, + LPCTSTR User, + TCHAR Perm) +{ + /* TODO & FIXME */ + switch(Perm) + { + case _T('N'): // None + break; + case _T('R'): // Read + break; + case _T('W'): // Write + break; + case _T('C'): // Change (write) + break; + case _T('F'): // Full control + break; + default: + break; + } + return FALSE; +} + +static BOOL +DenyUserAccess(LPCTSTR FilePath, LPCTSTR File, LPCTSTR User) +{ + /* TODO & FIXME */ + return FALSE; +} + +static BOOL +RevokeUserAccessRights(LPCTSTR FilePath, LPCTSTR File, LPCTSTR User) +{ + /* TODO & FIXME */ + return FALSE; +} + +static BOOL +ChangeFileACL(LPCTSTR FilePath, LPCTSTR File) +{ + if (OptionG) + { + /* Grant specified user access rights. */ + GrantUserAccessRights(FilePath, File, GUser, *GPerm); + } + + if (OptionP) + { + if (!OptionE) { - if (FilePart != NULL) - *FilePart = _T('\0'); + /* Replace specified user's access rights. */ + ReplaceUserAccessRights(FilePath, File, PUser, *PPerm); } else - goto Error; + { + /* Edit ACL instead of replacing it. */ + EditUserAccessRights(FilePath, File, PUser, *PPerm); + } + } - /* find the file(s) */ - hFind = FindFirstFile(argv[1], - &FindData); - if (hFind != INVALID_HANDLE_VALUE) + if (OptionD) + { + /* Deny specified user access. */ + DenyUserAccess(FilePath, File, DUser); + } + + if (OptionR) + { + /* Revoke specified user's access rights. */ + RevokeUserAccessRights(FilePath, File, RUser); + } + + return TRUE; +} + +static BOOL +ChangeACLsOfFiles(LPCTSTR pszFiles) +{ + TCHAR FilePath[MAX_PATH]; + HANDLE hFind; + WIN32_FIND_DATA FindData; + DWORD LastError; + + /* + * get the file path + */ + if (!GetPathOfFile(FilePath, pszFiles)) + return FALSE; + + /* + * search for files in current directory + */ + hFind = FindFirstFile(pszFiles, &FindData); + if (hFind == INVALID_HANDLE_VALUE) + return FALSE; + do + { + if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + continue; + + if (!ChangeFileACL(FilePath, FindData.cFileName)) { - do + LastError = GetLastError(); + if (LastError == ERROR_ACCESS_DENIED) { - if (!(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) || - (_tcscmp(FindData.cFileName, - _T(".")) && - _tcscmp(FindData.cFileName, - _T("..")))) + PrintErrorMessage(LastError); + if (!OptionC) { - if (argc > 2) + FindClose(hFind); + return FALSE; + } + } + else + break; + } + } while(FindNextFile(hFind, &FindData)); + + LastError = GetLastError(); + FindClose(hFind); + + if (LastError != ERROR_NO_MORE_FILES) + { + PrintErrorMessage(LastError); + return FALSE; + } + + return TRUE; +} + +static BOOL +ChangeACLsOfFilesInCurDir(LPCTSTR pszFiles) +{ + HANDLE hFind; + WIN32_FIND_DATA FindData; + TCHAR szCurDir[MAX_PATH]; + DWORD LastError; + + /* + * get the file path (current directory) + */ + GetCurrentDirectory(MAX_PATH, szCurDir); + AddBackslash(szCurDir); + + /* + * search for files in current directory + */ + hFind = FindFirstFile(pszFiles, &FindData); + if (hFind == INVALID_HANDLE_VALUE) + return FALSE; + do + { + if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + continue; + + if (!ChangeFileACL(szCurDir, FindData.cFileName)) + { + LastError = GetLastError(); + if (LastError == ERROR_ACCESS_DENIED) + { + PrintErrorMessage(LastError); + if (!OptionC) + { + FindClose(hFind); + return FALSE; + } + } + else + break; + } + } while(FindNextFile(hFind, &FindData)); + + LastError = GetLastError(); + FindClose(hFind); + + if (LastError != ERROR_NO_MORE_FILES) + { + PrintErrorMessage(LastError); + return FALSE; + } + + /* + * search for subdirectory in current directory + */ + hFind = FindFirstFile(_T("*"), &FindData); + if (hFind == INVALID_HANDLE_VALUE) + return FALSE; + do + { + if (_tcscmp(FindData.cFileName, _T(".")) == 0 || + _tcscmp(FindData.cFileName, _T("..")) == 0) + continue; + + if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + GetCurrentDirectory(MAX_PATH, szCurDir); + if (SetCurrentDirectory(FindData.cFileName)) + { + ChangeACLsOfFilesInCurDir(pszFiles); + SetCurrentDirectory(szCurDir); + } + else + { + LastError = GetLastError(); + if (LastError == ERROR_ACCESS_DENIED) + { + PrintErrorMessage(LastError); + if (!OptionC) { - /* FIXME - edit or replace the descriptor */ + FindClose(hFind); + return FALSE; } - else - { - if (!PrintFileDacl(FullPath, - FindData.cFileName)) - { - LastError = GetLastError(); - - if (LastError == ERROR_ACCESS_DENIED) - { - PrintErrorMessage(LastError); - } - else - break; - } - else - _tprintf(_T("\n")); - } } - } while (FindNextFile(hFind, - &FindData)); + else + break; + } + } + } while(FindNextFile(hFind, &FindData)); + LastError = GetLastError(); + FindClose(hFind); - FindClose(hFind); + if (LastError != ERROR_NO_MORE_FILES) + { + PrintErrorMessage(LastError); + return FALSE; + } + return TRUE; +} - if (GetLastError() != ERROR_NO_MORE_FILES) +int +__cdecl +_tmain(int argc, const TCHAR *argv[]) +{ + INT i; + LPTSTR pch; + BOOL InvalidParameter = FALSE; + + if (argc <= 1) + { + PrintHelp(); + return 0; + } + + /* + * parse command line options + */ + for(i = 2; i < argc; i++) + { + if (lstrcmpi(argv[i], _T("/T")) == 0) + { + OptionT = TRUE; + } + else if (lstrcmpi(argv[i], _T("/E")) == 0) + { + OptionE = TRUE; + } + else if (lstrcmpi(argv[i], _T("/C")) == 0) + { + OptionC = TRUE; + } + else if (lstrcmpi(argv[i], _T("/G")) == 0) + { + if (i + 1 < argc) { - goto Error; + pch = _tcschr(argv[++i], _T(':')); + if (pch != NULL) + { + OptionG = TRUE; + *pch = 0; + GUser = argv[i]; + GPerm = pch + 1; + continue; + } } + InvalidParameter = TRUE; + break; } + else if (lstrcmpi(argv[i], _T("/R")) == 0) + { + if (i + 1 < argc) + { + RUser = argv[++i]; + OptionR = TRUE; + continue; + } + InvalidParameter = TRUE; + break; + } + else if (lstrcmpi(argv[i], _T("/P")) == 0) + { + if (i + 1 < argc) + { + pch = _tcschr(argv[++i], _T(':')); + if (pch != NULL) + { + OptionP = TRUE; + *pch = 0; + PUser = argv[i]; + PPerm = pch + 1; + continue; + } + } + InvalidParameter = TRUE; + break; + } + else if (lstrcmpi(argv[i], _T("/D")) == 0) + { + if (i + 1 < argc) + { + OptionD = TRUE; + DUser = argv[++i]; + continue; + } + InvalidParameter = TRUE; + break; + } else { -Error: - PrintErrorMessage(GetLastError()); - return 1; + InvalidParameter = TRUE; + break; } } + if (InvalidParameter) + { + PrintErrorMessage(ERROR_INVALID_PARAMETER); + PrintHelp(); + return 1; + } + + /* /R is only valid with /E */ + if (OptionR && !OptionE) + { + OptionR = FALSE; + } + + PrintDaclsOfFiles(argv[1]); + + if (OptionT) + { + ChangeACLsOfFilesInCurDir(argv[1]); + } + else + { + ChangeACLsOfFiles(argv[1]); + } + return 0; }