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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 static GENERIC_MAPPING FileGenericMapping
=
33 LengthOfStrResource(IN HINSTANCE hInst
,
42 hInst
= GetModuleHandle(NULL
);
45 /* There are always blocks of 16 strings */
46 lpName
= (LPWSTR
)MAKEINTRESOURCE((uID
>> 4) + 1);
48 /* Find the string table block */
49 hrSrc
= FindResourceW(hInst
, lpName
, (LPWSTR
)RT_STRING
);
52 hRes
= LoadResource(hInst
, hrSrc
);
55 lpStr
= LockResource(hRes
);
60 /* Find the string we're looking for */
61 uID
&= 0xF; /* position in the block, same as % 16 */
62 for (x
= 0; x
< uID
; x
++)
64 lpStr
+= (*lpStr
) + 1;
67 /* Found the string */
78 AllocAndLoadString(OUT LPTSTR
*lpTarget
,
84 ln
= LengthOfStrResource(hInst
,
88 (*lpTarget
) = (LPTSTR
)HeapAlloc(GetProcessHeap(),
91 if ((*lpTarget
) != NULL
)
94 Ret
= LoadString(hInst
,
100 HeapFree(GetProcessHeap(),
117 if (AllocAndLoadString(&szHelp
,
124 HeapFree(GetProcessHeap(),
133 PrintErrorMessage(IN DWORD dwError
)
137 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
138 FORMAT_MESSAGE_IGNORE_INSERTS
|
139 FORMAT_MESSAGE_FROM_SYSTEM
,
142 MAKELANGID(LANG_NEUTRAL
,
150 LocalFree((HLOCAL
)szError
);
157 LoadAndPrintString(IN HINSTANCE hInst
,
163 Len
= (DWORD
)LoadString(hInst
,
166 sizeof(szTemp
) / sizeof(szTemp
[0]));
180 PrintFileDacl(IN LPTSTR FilePath
,
184 PSECURITY_DESCRIPTOR SecurityDescriptor
;
186 TCHAR FullFileName
[MAX_PATH
+ 1];
187 BOOL Error
= FALSE
, Ret
= FALSE
;
189 Length
= _tcslen(FilePath
) + _tcslen(FileName
);
190 if (Length
> MAX_PATH
)
192 /* file name too long */
193 SetLastError(ERROR_FILE_NOT_FOUND
);
197 _tcscpy(FullFileName
,
199 _tcscat(FullFileName
,
202 /* find out how much memory we need */
203 if (!GetFileSecurity(FullFileName
,
204 DACL_SECURITY_INFORMATION
,
208 GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
213 SecurityDescriptor
= (PSECURITY_DESCRIPTOR
)HeapAlloc(GetProcessHeap(),
216 if (SecurityDescriptor
!= NULL
)
218 if (GetFileSecurity(FullFileName
,
219 DACL_SECURITY_INFORMATION
,
228 if (GetSecurityDescriptorDacl(SecurityDescriptor
,
235 PACCESS_ALLOWED_ACE Ace
;
245 DWORD DomainSize
= 0;
247 LPTSTR Domain
= NULL
;
248 LPTSTR SidString
= NULL
;
250 DWORD AccessMask
= Ace
->Mask
;
251 PSID Sid
= (PSID
)&Ace
->SidStart
;
253 /* attempt to translate the SID into a readable string */
254 if (!LookupAccountSid(NULL
,
262 if (GetLastError() == ERROR_NONE_MAPPED
|| NameSize
== 0)
268 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
274 Name
= (LPTSTR
)HeapAlloc(GetProcessHeap(),
276 (NameSize
+ DomainSize
) * sizeof(TCHAR
));
279 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
284 Domain
= Name
+ NameSize
;
287 Domain
[0] = _T('\0');
288 if (!LookupAccountSid(NULL
,
296 HeapFree(GetProcessHeap(),
307 if (!ConvertSidToStringSid(Sid
,
315 /* print the file name or space */
319 /* attempt to map the SID to a user name */
324 /* overwrite the full file name with spaces so we
325 only print the file name once */
326 while (FullFileName
[i
] != _T('\0'))
327 FullFileName
[i
++] = _T(' ');
330 /* print the domain and/or user if possible, or the SID string */
331 if (Name
!= NULL
&& Domain
[0] != _T('\0'))
333 _tprintf(_T("%s\\%s:"),
336 IndentAccess
= (DWORD
)_tcslen(Domain
) + _tcslen(Name
);
340 LPTSTR DisplayString
= (Name
!= NULL
? Name
: SidString
);
344 IndentAccess
= (DWORD
)_tcslen(DisplayString
);
347 /* print the ACE Flags */
348 if (Ace
->Header
.AceFlags
& CONTAINER_INHERIT_ACE
)
350 IndentAccess
+= LoadAndPrintString(NULL
,
353 if (Ace
->Header
.AceFlags
& OBJECT_INHERIT_ACE
)
355 IndentAccess
+= LoadAndPrintString(NULL
,
358 if (Ace
->Header
.AceFlags
& INHERIT_ONLY_ACE
)
360 IndentAccess
+= LoadAndPrintString(NULL
,
366 /* print the access rights */
367 MapGenericMask(&AccessMask
,
368 &FileGenericMapping
);
369 if (Ace
->Header
.AceType
& ACCESS_DENIED_ACE_TYPE
)
371 if (AccessMask
== FILE_ALL_ACCESS
)
373 LoadAndPrintString(NULL
,
378 LoadAndPrintString(NULL
,
380 goto PrintSpecialAccess
;
385 if (AccessMask
== FILE_ALL_ACCESS
)
387 LoadAndPrintString(NULL
,
390 else if (!(Ace
->Mask
& (GENERIC_READ
| GENERIC_EXECUTE
)) &&
391 AccessMask
== (FILE_GENERIC_READ
| FILE_EXECUTE
))
393 LoadAndPrintString(NULL
,
396 else if (AccessMask
== (FILE_GENERIC_READ
| FILE_GENERIC_WRITE
| FILE_EXECUTE
| DELETE
))
398 LoadAndPrintString(NULL
,
401 else if (AccessMask
== FILE_GENERIC_WRITE
)
403 LoadAndPrintString(NULL
,
416 {FILE_WRITE_ATTRIBUTES
, IDS_FILE_WRITE_ATTRIBUTES
},
417 {FILE_READ_ATTRIBUTES
, IDS_FILE_READ_ATTRIBUTES
},
418 {FILE_DELETE_CHILD
, IDS_FILE_DELETE_CHILD
},
419 {FILE_EXECUTE
, IDS_FILE_EXECUTE
},
420 {FILE_WRITE_EA
, IDS_FILE_WRITE_EA
},
421 {FILE_READ_EA
, IDS_FILE_READ_EA
},
422 {FILE_APPEND_DATA
, IDS_FILE_APPEND_DATA
},
423 {FILE_WRITE_DATA
, IDS_FILE_WRITE_DATA
},
424 {FILE_READ_DATA
, IDS_FILE_READ_DATA
},
425 {FILE_GENERIC_EXECUTE
, IDS_FILE_GENERIC_EXECUTE
},
426 {FILE_GENERIC_WRITE
, IDS_FILE_GENERIC_WRITE
},
427 {FILE_GENERIC_READ
, IDS_FILE_GENERIC_READ
},
428 {GENERIC_ALL
, IDS_GENERIC_ALL
},
429 {GENERIC_EXECUTE
, IDS_GENERIC_EXECUTE
},
430 {GENERIC_WRITE
, IDS_GENERIC_WRITE
},
431 {GENERIC_READ
, IDS_GENERIC_READ
},
432 {MAXIMUM_ALLOWED
, IDS_MAXIMUM_ALLOWED
},
433 {ACCESS_SYSTEM_SECURITY
, IDS_ACCESS_SYSTEM_SECURITY
},
434 {SPECIFIC_RIGHTS_ALL
, IDS_SPECIFIC_RIGHTS_ALL
},
435 {STANDARD_RIGHTS_REQUIRED
, IDS_STANDARD_RIGHTS_REQUIRED
},
436 {SYNCHRONIZE
, IDS_SYNCHRONIZE
},
437 {WRITE_OWNER
, IDS_WRITE_OWNER
},
438 {WRITE_DAC
, IDS_WRITE_DAC
},
439 {READ_CONTROL
, IDS_READ_CONTROL
},
440 {DELETE
, IDS_DELETE
},
441 {STANDARD_RIGHTS_ALL
, IDS_STANDARD_RIGHTS_ALL
},
444 LoadAndPrintString(NULL
,
448 LoadAndPrintString(NULL
,
451 /* print the special access rights */
452 x
= sizeof(AccessRights
) / sizeof(AccessRights
[0]);
455 if ((Ace
->Mask
& AccessRights
[x
].Access
) == AccessRights
[x
].Access
)
457 _tprintf(_T("\n%s "),
466 LoadAndPrintString(NULL
,
467 AccessRights
[x
].uID
);
477 /* free up all resources */
480 HeapFree(GetProcessHeap(),
485 if (SidString
!= NULL
)
487 LocalFree((HLOCAL
)SidString
);
498 SetLastError(ERROR_NO_SECURITY_ON_OBJECT
);
503 HeapFree(GetProcessHeap(),
509 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
518 _tmain(int argc
, const TCHAR
*argv
[])
527 TCHAR FullPath
[MAX_PATH
+ 1];
528 TCHAR
*FilePart
= NULL
;
529 WIN32_FIND_DATA FindData
;
535 /* FIXME - parse arguments */
538 /* get the full path of where we're searching in */
539 if (GetFullPathName(argv
[1],
540 sizeof(FullPath
) / sizeof(FullPath
[0]),
544 if (FilePart
!= NULL
)
545 *FilePart
= _T('\0');
550 /* find the file(s) */
551 hFind
= FindFirstFile(argv
[1],
553 if (hFind
!= INVALID_HANDLE_VALUE
)
557 if (!(FindData
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) ||
558 (_tcscmp(FindData
.cFileName
,
560 _tcscmp(FindData
.cFileName
,
565 /* FIXME - edit or replace the descriptor */
569 if (!PrintFileDacl(FullPath
,
572 LastError
= GetLastError();
574 if (LastError
== ERROR_ACCESS_DENIED
)
576 PrintErrorMessage(LastError
);
585 } while (FindNextFile(hFind
,
590 if (GetLastError() != ERROR_NO_MORE_FILES
)
598 PrintErrorMessage(GetLastError());