Index: base/applications/cacls/cacls.c =================================================================== --- base/applications/cacls/cacls.c (revision 57785) +++ base/applications/cacls/cacls.c (working copy) @@ -19,6 +19,13 @@ #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, @@ -28,10 +35,8 @@ }; -static -INT -LengthOfStrResource(IN HINSTANCE hInst, - IN UINT uID) +static INT +LengthOfStrResource(IN HINSTANCE hInst, IN UINT uID) { HRSRC hrSrc; HGLOBAL hRes; @@ -73,33 +78,24 @@ } -static -INT -AllocAndLoadString(OUT LPTSTR *lpTarget, - IN HINSTANCE hInst, - IN UINT uID) +static INT +AllocAndLoadString(OUT LPTSTR *lpTarget, IN HINSTANCE hInst, IN UINT uID) { - INT ln; + INT len; - ln = LengthOfStrResource(hInst, - uID); - if (ln++ > 0) + len = LengthOfStrResource(hInst, uID); + if (len++ > 0) { (*lpTarget) = (LPTSTR)HeapAlloc(GetProcessHeap(), 0, - ln * sizeof(TCHAR)); + len * sizeof(TCHAR)); if ((*lpTarget) != NULL) { INT Ret; - Ret = LoadString(hInst, - uID, - *lpTarget, - ln); + Ret = LoadString(hInst, uID, *lpTarget, len); if (!Ret) { - HeapFree(GetProcessHeap(), - 0, - *lpTarget); + HeapFree(GetProcessHeap(), 0, *lpTarget); } return Ret; } @@ -108,28 +104,19 @@ } -static -VOID +static VOID PrintHelp(VOID) { LPTSTR szHelp; - - if (AllocAndLoadString(&szHelp, - NULL, - IDS_HELP) != 0) + if (AllocAndLoadString(&szHelp, NULL, IDS_HELP) != 0) { - _tprintf(_T("%s"), - szHelp); - - HeapFree(GetProcessHeap(), - 0, - szHelp); + _tprintf(_T("%s"), szHelp); + HeapFree(GetProcessHeap(), 0, szHelp); } } -static -VOID +static VOID PrintErrorMessage(IN DWORD dwError) { LPTSTR szError; @@ -139,23 +126,19 @@ FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, - MAKELANGID(LANG_NEUTRAL, - SUBLANG_DEFAULT), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&szError, 0, NULL) != 0) { - _tprintf(_T("%s"), - szError); + _tprintf(_T("%s"), szError); LocalFree((HLOCAL)szError); } } -static -DWORD -LoadAndPrintString(IN HINSTANCE hInst, - IN UINT uID) +static DWORD +LoadAndPrintString(IN HINSTANCE hInst, IN UINT uID) { TCHAR szTemp[255]; DWORD Len; @@ -164,21 +147,17 @@ uID, szTemp, sizeof(szTemp) / sizeof(szTemp[0])); - if (Len != 0) { - _tprintf(_T("%s"), - szTemp); + _tprintf(_T("%s"), szTemp); } return Len; } -static -BOOL -PrintFileDacl(IN LPTSTR FilePath, - IN LPTSTR FileName) +static BOOL +PrintFileDacl(IN LPTSTR FilePath, IN LPTSTR FileName) { SIZE_T Length; PSECURITY_DESCRIPTOR SecurityDescriptor; @@ -194,10 +173,8 @@ return FALSE; } - _tcscpy(FullFileName, - FilePath); - _tcscat(FullFileName, - FileName); + _tcscpy(FullFileName, FilePath); + _tcscat(FullFileName, FileName); /* find out how much memory we need */ if (!GetFileSecurity(FullFileName, @@ -222,8 +199,7 @@ &SDSize)) { PACL Dacl; - BOOL DaclPresent; - BOOL DaclDefaulted; + BOOL DaclPresent, DaclDefaulted; if (GetSecurityDescriptorDacl(SecurityDescriptor, &DaclPresent, @@ -293,9 +269,7 @@ &DomainSize, &Use)) { - HeapFree(GetProcessHeap(), - 0, - Name); + HeapFree(GetProcessHeap(), 0, Name); Name = NULL; goto BuildSidString; } @@ -304,8 +278,7 @@ else { BuildSidString: - if (!ConvertSidToStringSid(Sid, - &SidString)) + if (!ConvertSidToStringSid(Sid, &SidString)) { Error = TRUE; break; @@ -313,8 +286,7 @@ } /* print the file name or space */ - _tprintf(_T("%s "), - FullFileName); + _tprintf(_T("%s "), FullFileName); /* attempt to map the SID to a user name */ if (AceIndex == 0) @@ -330,35 +302,29 @@ /* print the domain and/or user if possible, or the SID string */ if (Name != NULL && Domain[0] != _T('\0')) { - _tprintf(_T("%s\\%s:"), - Domain, - Name); + _tprintf(_T("%s\\%s:"), Domain, Name); IndentAccess = (DWORD)_tcslen(Domain) + _tcslen(Name); } else { LPTSTR DisplayString = (Name != NULL ? Name : SidString); - _tprintf(_T("%s:"), - DisplayString); + _tprintf(_T("%s:"), DisplayString); IndentAccess = (DWORD)_tcslen(DisplayString); } /* print the ACE Flags */ if (Ace->Header.AceFlags & CONTAINER_INHERIT_ACE) { - IndentAccess += LoadAndPrintString(NULL, - IDS_ABBR_CI); + IndentAccess += LoadAndPrintString(NULL, IDS_ABBR_CI); } if (Ace->Header.AceFlags & OBJECT_INHERIT_ACE) { - IndentAccess += LoadAndPrintString(NULL, - IDS_ABBR_OI); + IndentAccess += LoadAndPrintString(NULL, IDS_ABBR_OI); } if (Ace->Header.AceFlags & INHERIT_ONLY_ACE) { - IndentAccess += LoadAndPrintString(NULL, - IDS_ABBR_IO); + IndentAccess += LoadAndPrintString(NULL, IDS_ABBR_IO); } IndentAccess += 2; @@ -370,13 +336,11 @@ { if (AccessMask == FILE_ALL_ACCESS) { - LoadAndPrintString(NULL, - IDS_ABBR_NONE); + LoadAndPrintString(NULL, IDS_ABBR_NONE); } else { - LoadAndPrintString(NULL, - IDS_DENY); + LoadAndPrintString(NULL, IDS_DENY); goto PrintSpecialAccess; } } @@ -384,24 +348,20 @@ { if (AccessMask == FILE_ALL_ACCESS) { - LoadAndPrintString(NULL, - IDS_ABBR_FULL); + LoadAndPrintString(NULL, IDS_ABBR_FULL); } else if (!(Ace->Mask & (GENERIC_READ | GENERIC_EXECUTE)) && AccessMask == (FILE_GENERIC_READ | FILE_EXECUTE)) { - LoadAndPrintString(NULL, - IDS_ABBR_READ); + LoadAndPrintString(NULL, IDS_ABBR_READ); } else if (AccessMask == (FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_EXECUTE | DELETE)) { - LoadAndPrintString(NULL, - IDS_ABBR_CHANGE); + LoadAndPrintString(NULL, IDS_ABBR_CHANGE); } else if (AccessMask == FILE_GENERIC_WRITE) { - LoadAndPrintString(NULL, - IDS_ABBR_WRITE); + LoadAndPrintString(NULL, IDS_ABBR_WRITE); } else { @@ -441,12 +401,10 @@ {STANDARD_RIGHTS_ALL, IDS_STANDARD_RIGHTS_ALL}, }; - LoadAndPrintString(NULL, - IDS_ALLOW); + LoadAndPrintString(NULL, IDS_ALLOW); PrintSpecialAccess: - LoadAndPrintString(NULL, - IDS_SPECIAL_ACCESS); + LoadAndPrintString(NULL, IDS_SPECIAL_ACCESS); /* print the special access rights */ x = sizeof(AccessRights) / sizeof(AccessRights[0]); @@ -454,17 +412,14 @@ { if ((Ace->Mask & AccessRights[x].Access) == AccessRights[x].Access) { - _tprintf(_T("\n%s "), - FullFileName); - for (x2 = 0; - x2 < IndentAccess; - x2++) + _tprintf(_T("\n%s "), FullFileName); + + for (x2 = 0; x2 < IndentAccess; x2++) { _tprintf(_T(" ")); } - LoadAndPrintString(NULL, - AccessRights[x].uID); + LoadAndPrintString(NULL, AccessRights[x].uID); } } @@ -477,9 +432,7 @@ /* free up all resources */ if (Name != NULL) { - HeapFree(GetProcessHeap(), - 0, - Name); + HeapFree(GetProcessHeap(), 0, Name); } if (SidString != NULL) @@ -499,10 +452,7 @@ } } } - - HeapFree(GetProcessHeap(), - 0, - SecurityDescriptor); + HeapFree(GetProcessHeap(), 0, SecurityDescriptor); } else { @@ -513,92 +463,511 @@ } -int -__cdecl -_tmain(int argc, const TCHAR *argv[]) +/* add a backslash at end to a path string if necessary */ +static VOID +AddBackslash(LPTSTR FilePath) { - if (argc < 2) + INT len = lstrlen(FilePath); + LPTSTR pch = CharPrev(FilePath, FilePath + len); + if (*pch != _T('\\')) + lstrcat(pch, _T("\\")); +} + +/* get the file path of the specified files */ +static BOOL +GetFilePath(LPTSTR FilePath, LPCTSTR pszFiles) +{ + 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 (!GetFilePath(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 0 + if (_tcscmp(FindData.cFileName, _T(".")) == 0 || + _tcscmp(FindData.cFileName, _T("..")) == 0) + continue; +#endif + + 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)); - /* get the full path of where we're searching in */ - if (GetFullPathName(argv[1], - sizeof(FullPath) / sizeof(FullPath[0]), - FullPath, - &FilePart) != 0) + LastError = GetLastError(); + FindClose(hFind); + 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) +{ + /* TODO & FIXME */ + 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); + } + } + if (OptionD) + { + /* Deny specified user access. */ + DenyUserAccess(FilePath, File, DUser); + } + if (OptionR) + { + /* Revoke specified user's access rights. */ + RevokeUserAccessRights(FilePath, File, RUser); + } + return TRUE; +} - /* find the file(s) */ - hFind = FindFirstFile(argv[1], - &FindData); - if (hFind != INVALID_HANDLE_VALUE) +static BOOL +ChangeACLsOfFiles(LPCTSTR pszFiles) +{ + TCHAR FilePath[MAX_PATH]; + HANDLE hFind; + WIN32_FIND_DATA FindData; + DWORD LastError; + + /* + * get the file path + */ + if (!GetFilePath(FilePath, pszFiles)) + return FALSE; + + /* + * search for files in current directory + */ + hFind = FindFirstFile(pszFiles, &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)) { - do + if (!ChangeFileACL(FilePath, FindData.cFileName)) { - if (!(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) || - (_tcscmp(FindData.cFileName, - _T(".")) && - _tcscmp(FindData.cFileName, - _T("..")))) + LastError = GetLastError(); + if (LastError == ERROR_ACCESS_DENIED) { - if (argc > 2) + PrintErrorMessage(LastError); + if (!OptionC) { - /* FIXME - edit or replace the descriptor */ + FindClose(hFind); + return FALSE; } - else + } + 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 0 + if (_tcscmp(FindData.cFileName, _T(".")) == 0 || + _tcscmp(FindData.cFileName, _T("..")) == 0) + continue; +#endif + + if (!(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + if (!ChangeFileACL(szCurDir, FindData.cFileName)) + { + LastError = GetLastError(); + if (LastError == ERROR_ACCESS_DENIED) + { + PrintErrorMessage(LastError); + if (!OptionC) { - if (!PrintFileDacl(FullPath, - FindData.cFileName)) - { - LastError = GetLastError(); + FindClose(hFind); + return FALSE; + } + } + else + break; + } + } + } while(FindNextFile(hFind, &FindData)); - if (LastError == ERROR_ACCESS_DENIED) - { - PrintErrorMessage(LastError); - } - else - break; - } - else - _tprintf(_T("\n")); + 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) + { + FindClose(hFind); + return FALSE; } } - } while (FindNextFile(hFind, - &FindData)); + else + break; + } + } + } while(FindNextFile(hFind, &FindData)); + LastError = GetLastError(); + FindClose(hFind); + if (LastError != ERROR_NO_MORE_FILES) + { + PrintErrorMessage(LastError); + return FALSE; + } - FindClose(hFind); + 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]); + + /* TODO */ + if (OptionT) + { + ChangeACLsOfFilesInCurDir(argv[1]); + } + else + { + ChangeACLsOfFiles(argv[1]); + } + return 0; }