2 * ReactOS Control ACLs Program
3 * Copyright (C) 2006 Thomas Weidenmueller
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 static GENERIC_MAPPING FileGenericMapping
=
32 LengthOfStrResource(IN HINSTANCE hInst
,
41 hInst
= GetModuleHandle(NULL
);
44 /* There are always blocks of 16 strings */
45 lpName
= (LPWSTR
)MAKEINTRESOURCE((uID
>> 4) + 1);
47 /* Find the string table block */
48 hrSrc
= FindResourceW(hInst
, lpName
, (LPWSTR
)RT_STRING
);
51 hRes
= LoadResource(hInst
, hrSrc
);
54 lpStr
= LockResource(hRes
);
59 /* Find the string we're looking for */
60 uID
&= 0xF; /* position in the block, same as % 16 */
61 for (x
= 0; x
< uID
; x
++)
63 lpStr
+= (*lpStr
) + 1;
66 /* Found the string */
76 AllocAndLoadString(OUT LPTSTR
*lpTarget
,
82 ln
= LengthOfStrResource(hInst
,
86 (*lpTarget
) = (LPTSTR
)HeapAlloc(GetProcessHeap(),
89 if ((*lpTarget
) != NULL
)
92 Ret
= LoadString(hInst
,
98 HeapFree(GetProcessHeap(),
114 if (AllocAndLoadString(&szHelp
,
121 HeapFree(GetProcessHeap(),
129 PrintErrorMessage(IN DWORD dwError
)
133 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
134 FORMAT_MESSAGE_IGNORE_INSERTS
|
135 FORMAT_MESSAGE_FROM_SYSTEM
,
138 MAKELANGID(LANG_NEUTRAL
,
146 LocalFree((HLOCAL
)szError
);
152 LoadAndPrintString(IN HINSTANCE hInst
,
158 Len
= (DWORD
)LoadString(hInst
,
161 sizeof(szTemp
) / sizeof(szTemp
[0]));
174 PrintFileDacl(IN LPTSTR FilePath
,
178 PSECURITY_DESCRIPTOR SecurityDescriptor
;
180 TCHAR FullFileName
[MAX_PATH
+ 1];
181 BOOL Error
= FALSE
, Ret
= FALSE
;
183 Indent
= _tcslen(FilePath
) + _tcslen(FileName
);
184 if (Indent
++ > MAX_PATH
- 1)
186 /* file name too long */
187 SetLastError(ERROR_FILE_NOT_FOUND
);
191 _tcscpy(FullFileName
,
193 _tcscat(FullFileName
,
196 /* find out how much memory we need */
197 if (!GetFileSecurity(FullFileName
,
198 DACL_SECURITY_INFORMATION
,
202 GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
207 SecurityDescriptor
= (PSECURITY_DESCRIPTOR
)HeapAlloc(GetProcessHeap(),
210 if (SecurityDescriptor
!= NULL
)
212 if (GetFileSecurity(FullFileName
,
213 DACL_SECURITY_INFORMATION
,
222 if (GetSecurityDescriptorDacl(SecurityDescriptor
,
229 PACCESS_ALLOWED_ACE Ace
;
239 DWORD DomainSize
= 0;
241 LPTSTR Domain
= NULL
;
242 LPTSTR SidString
= NULL
;
244 DWORD AccessMask
= Ace
->Mask
;
245 PSID Sid
= (PSID
)&Ace
->SidStart
;
247 /* attempt to translate the SID into a readable string */
248 if (!LookupAccountSid(NULL
,
256 if (GetLastError() == ERROR_NONE_MAPPED
|| NameSize
== 0)
262 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
268 Name
= (LPTSTR
)HeapAlloc(GetProcessHeap(),
270 (NameSize
+ DomainSize
) * sizeof(TCHAR
));
273 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
278 Domain
= Name
+ NameSize
;
281 Domain
[0] = _T('\0');
282 if (!LookupAccountSid(NULL
,
290 HeapFree(GetProcessHeap(),
301 if (!ConvertSidToStringSid(Sid
,
309 /* print the file name or space */
313 /* attempt to map the SID to a user name */
318 /* overwrite the full file name with spaces so we
319 only print the file name once */
320 while (FullFileName
[i
] != _T('\0'))
321 FullFileName
[i
++] = _T(' ');
324 /* print the domain and/or user if possible, or the SID string */
325 if (Name
!= NULL
&& Domain
[0] != _T('\0'))
327 _tprintf(_T("%s\\%s:"),
330 IndentAccess
= (DWORD
)_tcslen(Domain
) + _tcslen(Name
);
334 LPTSTR DisplayString
= (Name
!= NULL
? Name
: SidString
);
338 IndentAccess
= (DWORD
)_tcslen(DisplayString
);
341 /* print the ACE Flags */
342 if (Ace
->Header
.AceFlags
& CONTAINER_INHERIT_ACE
)
344 IndentAccess
+= LoadAndPrintString(NULL
,
347 if (Ace
->Header
.AceFlags
& OBJECT_INHERIT_ACE
)
349 IndentAccess
+= LoadAndPrintString(NULL
,
352 if (Ace
->Header
.AceFlags
& INHERIT_ONLY_ACE
)
354 IndentAccess
+= LoadAndPrintString(NULL
,
360 /* print the access rights */
361 MapGenericMask(&AccessMask
,
362 &FileGenericMapping
);
363 if (Ace
->Header
.AceType
& ACCESS_DENIED_ACE_TYPE
)
365 if (AccessMask
== FILE_ALL_ACCESS
)
367 LoadAndPrintString(NULL
,
372 LoadAndPrintString(NULL
,
374 goto PrintSpecialAccess
;
379 if (AccessMask
== FILE_ALL_ACCESS
)
381 LoadAndPrintString(NULL
,
384 else if (!(Ace
->Mask
& (GENERIC_READ
| GENERIC_EXECUTE
)) &&
385 AccessMask
== (FILE_GENERIC_READ
| FILE_EXECUTE
))
387 LoadAndPrintString(NULL
,
390 else if (AccessMask
== (FILE_GENERIC_READ
| FILE_GENERIC_WRITE
| FILE_EXECUTE
| DELETE
))
392 LoadAndPrintString(NULL
,
395 else if (AccessMask
== FILE_GENERIC_WRITE
)
397 LoadAndPrintString(NULL
,
410 {FILE_WRITE_ATTRIBUTES
, IDS_FILE_WRITE_ATTRIBUTES
},
411 {FILE_READ_ATTRIBUTES
, IDS_FILE_READ_ATTRIBUTES
},
412 {FILE_DELETE_CHILD
, IDS_FILE_DELETE_CHILD
},
413 {FILE_EXECUTE
, IDS_FILE_EXECUTE
},
414 {FILE_WRITE_EA
, IDS_FILE_WRITE_EA
},
415 {FILE_READ_EA
, IDS_FILE_READ_EA
},
416 {FILE_APPEND_DATA
, IDS_FILE_APPEND_DATA
},
417 {FILE_WRITE_DATA
, IDS_FILE_WRITE_DATA
},
418 {FILE_READ_DATA
, IDS_FILE_READ_DATA
},
419 {FILE_GENERIC_EXECUTE
, IDS_FILE_GENERIC_EXECUTE
},
420 {FILE_GENERIC_WRITE
, IDS_FILE_GENERIC_WRITE
},
421 {FILE_GENERIC_READ
, IDS_FILE_GENERIC_READ
},
422 {GENERIC_ALL
, IDS_GENERIC_ALL
},
423 {GENERIC_EXECUTE
, IDS_GENERIC_EXECUTE
},
424 {GENERIC_WRITE
, IDS_GENERIC_WRITE
},
425 {GENERIC_READ
, IDS_GENERIC_READ
},
426 {MAXIMUM_ALLOWED
, IDS_MAXIMUM_ALLOWED
},
427 {ACCESS_SYSTEM_SECURITY
, IDS_ACCESS_SYSTEM_SECURITY
},
428 {SPECIFIC_RIGHTS_ALL
, IDS_SPECIFIC_RIGHTS_ALL
},
429 {STANDARD_RIGHTS_REQUIRED
, IDS_STANDARD_RIGHTS_REQUIRED
},
430 {SYNCHRONIZE
, IDS_SYNCHRONIZE
},
431 {WRITE_OWNER
, IDS_WRITE_OWNER
},
432 {WRITE_DAC
, IDS_WRITE_DAC
},
433 {READ_CONTROL
, IDS_READ_CONTROL
},
434 {DELETE
, IDS_DELETE
},
435 {STANDARD_RIGHTS_ALL
, IDS_STANDARD_RIGHTS_ALL
},
438 LoadAndPrintString(NULL
,
442 LoadAndPrintString(NULL
,
445 /* print the special access rights */
446 x
= sizeof(AccessRights
) / sizeof(AccessRights
[0]);
449 if ((Ace
->Mask
& AccessRights
[x
].Access
) == AccessRights
[x
].Access
)
451 _tprintf(_T("\n%s "),
460 LoadAndPrintString(NULL
,
461 AccessRights
[x
].uID
);
471 /* free up all resources */
474 HeapFree(GetProcessHeap(),
479 if (SidString
!= NULL
)
481 LocalFree((HLOCAL
)SidString
);
492 SetLastError(ERROR_NO_SECURITY_ON_OBJECT
);
497 HeapFree(GetProcessHeap(),
503 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
510 int __cdecl
_tmain(int argc
, const TCHAR
*argv
[])
519 TCHAR FullPath
[MAX_PATH
+ 1];
520 TCHAR
*FilePart
= NULL
;
521 WIN32_FIND_DATA FindData
;
524 BOOL ContinueAccessDenied
= FALSE
;
528 /* FIXME - parse arguments */
531 /* get the full path of where we're searching in */
532 if (GetFullPathName(argv
[1],
533 sizeof(FullPath
) / sizeof(FullPath
[0]),
537 if (FilePart
!= NULL
)
538 *FilePart
= _T('\0');
543 /* find the file(s) */
544 hFind
= FindFirstFile(argv
[1],
546 if (hFind
!= INVALID_HANDLE_VALUE
)
550 if (!(FindData
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) ||
551 (_tcscmp(FindData
.cFileName
,
553 _tcscmp(FindData
.cFileName
,
558 /* FIXME - edit or replace the descriptor */
562 if (!PrintFileDacl(FullPath
,
565 LastError
= GetLastError();
567 if (LastError
== ERROR_ACCESS_DENIED
&&
568 ContinueAccessDenied
)
570 PrintErrorMessage(LastError
);
579 } while (FindNextFile(hFind
,
584 if (GetLastError() != ERROR_NO_MORE_FILES
)
592 PrintErrorMessage(GetLastError());