Thanks,
Anthony
Check out VB sample code in
Q240176 - HOWTO: Set Security on a NTFS Folder Programmatically
http://support.microsoft.com/support/kb/articles/Q240/1/76.asp
ADSI method
Q279682 - HOWTO: Use ADsSecurity.dll to Add an Access Control Entry to an
NTFS Folder
http://support.microsoft.com/support/kb/articles/Q279/6/82.asp
and 'C' sample code in
Q102102 - HOWTO: Add an Access-Allowed ACE to a File
http://support.microsoft.com/support/kb/articles/Q102/1/02.asp
The code in article Q102102 does only for files and adds ACCESS_ALLOWED_ACE
always at the end of the DACL.
If you are on Window 2000, you have to add this ACE "before" any
INHERITED_ACEs that you have in the Existing DACL and that is the only
change you need.
The ACE specification for Container Objects like a directory is explained in
Q188760 - HOWTO: Specify Access Control on Window NT/Windows 2000 Container
Objects
http://support.microsoft.com/support/kb/articles/Q188/7/60.asp
Thanks,
Prabagar
"Anthony Hunter" <anthony...@wonderware.com> wrote in message
news:3AF56AE5...@wonderware.com...
Anthony
If you want to target only on Windows 2000, you can look at ACLAPI sample in
Microsoft Platform SDK. It is located in
%MSSDK%\Samples\WinBase\Security\WinNT\AclApi folder after Installing
Microsoft Platform SDK samples from
http://www.microsoft.com/msdownload/platformsdk/setuplauncher.asp
It has examples of GRANT_ACCESS as well as SET_ACCESS mode using
EXPLICIT_ACCESS structures.
GRANT_ACCESS
An input flag that creates an ACCESS_ALLOWED_ACE. The new ACE combines the
specified rights with any existing allowed or denied rights of the trustee.
SET_ACCESS
Indicates an ACCESS_ALLOWED_ACE that allows the specified rights. On input,
this flag discards any existing access-control information for the trustee.
Thanks,
Prabagar
"Anthony Hunter" <anthony...@wonderware.com> wrote in message
news:3B02A4D5...@wonderware.com...
Thanks,
GetExplicitEntriesFromAcl() has a known bug on Windows 2000 as explained in
the following knowledge base article.
Q260307 - INFO: The GetExplicitEntriesFromAcl() Function Returns the
Incorrect Number of ACEs
http://support.microsoft.com/support/kb/articles/Q260/3/07.asp
Do not use this API. The AclApi Microsoft Platform SDK sample does not use
this API.
The Aclapi sample should work fine on Windows 2000.
The following options
aclapi c:\test /Set Administrator 2032127 3
will add "Administrator" "Full Control" permissions to c:\test folder and
the ACE is inheritable by subfolders as well as files.
If you specify inheritance of 0, then the ACE is applicable only for the
folder.
If you specify OBJECT_INHERIT_ACE in inheritance, the ACE will be inherited
by files.
If you specify CONTAINER_INHERIT_ACE in inheritance, the ACE will be
inherited by subfolders.
2032127 in the command line above is the access mask that corresponds to
"Full Control" for file/folder securable object.
3 in the command line above is OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE
value.
Thanks,
Prabagar
"Anthony Hunter" <anthony...@wonderware.com> wrote in message
news:3B03E148...@wonderware.com...
aclapi d:\test /Set Everyone 3758161920 3
where 3758161920 is setting the group Everyone to Change access.
This works, but removes all other groups there were part of the permissions. If
I run the same command on a file it leaves everything in tack, and changes the
permissions on the group Everyone. Also, the subdirectories and files did not
inherit the new permissions. (or does that only apply to new files?)
Anthony
I tested the following on Windows 2000 as well as Windows 2000 Service Pack
1.
aclapi c:\test /Set Everyone 3758161920 3
It works as expected on both the folder as well as file. i.e. it either adds
or modifies the Everyone ACE to Modify access. All other ACEs are
"unaffected". Also, if applied on a folder, existing subfolders as well as
files inherit the Everyone ACE.
It is strange that this sample is not working on your Windows 2000 system.
My setup on the c:\test folder before running AclAPI sample, contains only
one ACE for "Administrators" Group expilicity specified with Full Control.
What setup do you have before running AclAPI sample? You can run Check_SD
sample from %MSSDK%\Samples\WinBase\Security\WinNT\Check_SD folder to dump
the SD information before and after running AclAPI sample.
I am not sure whether you are experimenting with the latest version of
Microsoft Platform SDK samples.
Below is the AclApi sample I am using
/********************/
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (C) 1996 - 2000. Microsoft Corporation. All rights reserved.
Module Name:
aclapi.c
Abstract:
This module illustrates new Acl management API for Windows NT 4.0.
Developers of new software which is to run on Windows NT version 4.0
and above are encouraged to utilize these security API rather than
implementing code which uses lower level security API. The development
and test time can be drastically reduced by utilizing these new API.
This sample illustrates this point by implementing code which modifies
the security on an existing file using the new Windows NT 4.0
Acl management API.
The following new API functions are illustrated in this sample:
GetNamedSecurityInfo()
BuildExplicitAccessWithName()
SetEntriesInAcl()
SetNamedSecurityInfo()
The following lower-level security API would have been used to achieve
the same result:
LookupAccountName()
InitializeSecurityDescriptor()
InitializeAcl()
GetSecurityDescriptorDacl()
GetAclInformation()
GetAce()
SetSecurityDescriptorDacl()
AddAce()
AddAccessAllowedAce() / AddAccessDeniedAce()
GetFileSecurity()
SetFileSecurity()
Less code and less complex code is required to achieve this task using
the new Windows NT 4.0 Acl management API.
--*/
#include <windows.h>
#include <aclapi.h>
#include <lmerr.h>
#include <stdio.h>
#define RTN_OK 0
#define RTN_USAGE 1
#define RTN_ERROR 13
void
DisplayLastError(
LPSTR szAPI
);
int
__cdecl
main(
int argc,
char *argv[]
)
{
LPTSTR FileName;
LPTSTR TrusteeName;
DWORD AccessMask = GENERIC_ALL;
DWORD InheritFlag = NO_INHERITANCE;
ACCESS_MODE option;
EXPLICIT_ACCESS explicitaccess;
PACL ExistingDacl;
PACL NewAcl = NULL;
PSECURITY_DESCRIPTOR psd = NULL;
DWORD dwError;
BOOL bSuccess = FALSE; // assume failure
if(argc < 4) {
printf("Usage: %s <filename> {/Deny | /Grant | /Revoke | /Set}
[<trustee>] [<permissions>] [<InheritFlag>]\n", argv[0]);
return RTN_USAGE;
}
FileName = argv[1];
TrusteeName = argv[3];
if ( (0 == stricmp(argv[2], "/Deny") ) ||
(0 == stricmp(argv[2], "/D") ) )
{
option = DENY_ACCESS;
} else if ( ( (0 == stricmp(argv[2], "/Revoke") ) ||
(0 == stricmp(argv[2], "/R") ) ) )
{
option = REVOKE_ACCESS;
} else if ( (0 == stricmp(argv[2], "/Set") ) ||
(0 == stricmp(argv[2], "/S") ) )
{
option = SET_ACCESS;
} else if ( (0 == stricmp(argv[2], "/Grant") ) ||
(0 == stricmp(argv[2], "/G") ) )
{
option = GRANT_ACCESS;
} else {
printf("Invalid action specified\n");
return RTN_ERROR;
}
if (argc > 4)
{
AccessMask = atol( argv[4] );
}
if (argc > 5)
{
InheritFlag = atol( argv[5] );
}
//
// get current Dacl on specified file
//
dwError = GetNamedSecurityInfo(
FileName,
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
NULL,
NULL,
&ExistingDacl,
NULL,
&psd
);
if(dwError != ERROR_SUCCESS) {
DisplayLastError("GetNamedSecurityInfo");
return RTN_ERROR;
}
BuildExplicitAccessWithName(
&explicitaccess,
TrusteeName,
AccessMask,
option,
InheritFlag
);
//
// add specified access to the object
//
dwError = SetEntriesInAcl(
1,
&explicitaccess,
ExistingDacl,
&NewAcl
);
if(dwError != ERROR_SUCCESS) {
DisplayLastError("SetEntriesInAcl");
goto cleanup;
}
//
// apply new security to file
//
dwError = SetNamedSecurityInfo(
FileName,
SE_FILE_OBJECT, // object type
DACL_SECURITY_INFORMATION,
NULL,
NULL,
NewAcl,
NULL
);
if(dwError != ERROR_SUCCESS) {
DisplayLastError("SetNamedSecurityInfo");
goto cleanup;
}
bSuccess = TRUE; // indicate success
cleanup:
if( NewAcl != NULL ) AccFree( NewAcl );
if( psd != NULL) AccFree( psd );
if(!bSuccess)
return RTN_ERROR;
return RTN_OK;
}
void
DisplayLastError(
LPSTR szAPI
)
{
HMODULE hModule = NULL; // default to system source
DWORD dwLastError = GetLastError();
LPSTR MessageBuffer;
DWORD dwBufferLength;
DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_FROM_SYSTEM ;
//
// if dwLastError is in the network range, load the message source
//
if(dwLastError >= NERR_BASE && dwLastError <= MAX_NERR) {
hModule = LoadLibraryEx(
TEXT("netmsg.dll"),
NULL,
LOAD_LIBRARY_AS_DATAFILE
);
if(hModule != NULL)
dwFormatFlags |= FORMAT_MESSAGE_FROM_HMODULE;
}
printf("%s error! (rc=%lu)\n", szAPI, dwLastError);
//
// call FormatMessage() to allow for message text to be acquired
// from the system or the supplied module handle
//
if(dwBufferLength = FormatMessageA(
dwFormatFlags,
hModule, // module to get message from (NULL == system)
dwLastError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
(LPSTR) &MessageBuffer,
0,
NULL
))
{
DWORD dwBytesWritten;
//
// Output message string on stderr
//
WriteFile(
GetStdHandle(STD_ERROR_HANDLE),
MessageBuffer,
dwBufferLength,
&dwBytesWritten,
NULL
);
//
// free the buffer allocated by the system
//
LocalFree(MessageBuffer);
}
//
// if we loaded a message source, unload it
//
if(hModule != NULL)
FreeLibrary(hModule);
}
/********************/
>or does that only apply to new files?)
When adding ACEs using SetNamedSecurityInfo() with inheritance value of 3,
"existing" files & subfolders will inherit that Everyone Change ACE through
Automatic inheritance only on Windows 2000.
Thanks,
Prabagar
"Anthony Hunter" <anthony...@wonderware.com> wrote in message
news:3B040226...@wonderware.com...