341 lines
8.3 KiB
C++
341 lines
8.3 KiB
C++
|
// PermPage.cpp : Implementation of data object classes
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
#include "cookie.h"
|
||
|
|
||
|
#include "macros.h"
|
||
|
USE_HANDLE_MACROS("FILEMGMT(PermPage.cpp)")
|
||
|
|
||
|
#include "DynamLnk.h" // DynamicDLL
|
||
|
|
||
|
#include "PermPage.h"
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
#define new DEBUG_NEW
|
||
|
#undef THIS_FILE
|
||
|
static char THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
|
||
|
/*
|
||
|
* Share General Permissions -- from shareacl.hxx
|
||
|
#define FILE_PERM_GEN_NO_ACCESS (0)
|
||
|
#define FILE_PERM_GEN_READ (GENERIC_READ |\
|
||
|
GENERIC_EXECUTE)
|
||
|
#define FILE_PERM_GEN_MODIFY (GENERIC_READ |\
|
||
|
GENERIC_EXECUTE |\
|
||
|
GENERIC_WRITE |\
|
||
|
DELETE )
|
||
|
#define FILE_PERM_GEN_ALL (GENERIC_ALL)
|
||
|
*/
|
||
|
|
||
|
SI_ACCESS siShareAccesses[] =
|
||
|
{
|
||
|
{ &GUID_NULL,
|
||
|
FILE_ALL_ACCESS,
|
||
|
MAKEINTRESOURCE(IDS_SHAREPERM_ALL),
|
||
|
SI_ACCESS_GENERAL },
|
||
|
{ &GUID_NULL,
|
||
|
FILE_GENERIC_READ | FILE_EXECUTE | FILE_GENERIC_WRITE | DELETE,
|
||
|
MAKEINTRESOURCE(IDS_SHAREPERM_MODIFY),
|
||
|
SI_ACCESS_GENERAL },
|
||
|
{ &GUID_NULL,
|
||
|
FILE_GENERIC_READ | FILE_EXECUTE,
|
||
|
MAKEINTRESOURCE(IDS_SHAREPERM_READ),
|
||
|
SI_ACCESS_GENERAL }
|
||
|
};
|
||
|
|
||
|
#define iShareDefAccess 2 // index of value in array siShareAccesses
|
||
|
#ifndef ARRAYSIZE
|
||
|
#define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
|
||
|
#endif
|
||
|
|
||
|
STDMETHODIMP
|
||
|
CSecurityInformation::GetAccessRights(
|
||
|
const GUID * /*pguidObjectType*/,
|
||
|
DWORD /*dwFlags*/,
|
||
|
PSI_ACCESS *ppAccess,
|
||
|
ULONG *pcAccesses,
|
||
|
ULONG *piDefaultAccess
|
||
|
)
|
||
|
{
|
||
|
ASSERT(ppAccess);
|
||
|
ASSERT(pcAccesses);
|
||
|
ASSERT(piDefaultAccess);
|
||
|
|
||
|
*ppAccess = siShareAccesses;
|
||
|
*pcAccesses = ARRAYSIZE(siShareAccesses);
|
||
|
*piDefaultAccess = iShareDefAccess;
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
// This is consistent with the NETUI code
|
||
|
GENERIC_MAPPING ShareMap =
|
||
|
{
|
||
|
FILE_GENERIC_READ,
|
||
|
FILE_GENERIC_WRITE,
|
||
|
FILE_GENERIC_EXECUTE,
|
||
|
FILE_ALL_ACCESS
|
||
|
};
|
||
|
|
||
|
STDMETHODIMP
|
||
|
CSecurityInformation::MapGeneric(
|
||
|
const GUID * /*pguidObjectType*/,
|
||
|
UCHAR * /*pAceFlags*/,
|
||
|
ACCESS_MASK *pMask
|
||
|
)
|
||
|
{
|
||
|
ASSERT(pMask);
|
||
|
|
||
|
MapGenericMask(pMask, &ShareMap);
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP
|
||
|
CSecurityInformation::GetInheritTypes (
|
||
|
PSI_INHERIT_TYPE * /*ppInheritTypes*/,
|
||
|
ULONG * /*pcInheritTypes*/
|
||
|
)
|
||
|
{
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP
|
||
|
CSecurityInformation::PropertySheetPageCallback(
|
||
|
HWND /*hwnd*/,
|
||
|
UINT /*uMsg*/,
|
||
|
SI_PAGE_TYPE /*uPage*/
|
||
|
)
|
||
|
{
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
JeffreyS 1/24/97:
|
||
|
If you don't set the SI_RESET flag in
|
||
|
ISecurityInformation::GetObjectInformation, then fDefault should never be TRUE
|
||
|
so you can ignore it. Returning E_NOTIMPL in this case is OK too.
|
||
|
|
||
|
If you want the user to be able to reset the ACL to some default state
|
||
|
(defined by you) then turn on SI_RESET and return your default ACL
|
||
|
when fDefault is TRUE. This happens if/when the user pushes a button
|
||
|
that is only visible when SI_RESET is on.
|
||
|
*/
|
||
|
STDMETHODIMP CShareSecurityInformation::GetObjectInformation (
|
||
|
PSI_OBJECT_INFO pObjectInfo )
|
||
|
{
|
||
|
ASSERT(pObjectInfo != NULL &&
|
||
|
!IsBadWritePtr(pObjectInfo, sizeof(*pObjectInfo)));
|
||
|
|
||
|
pObjectInfo->dwFlags = SI_EDIT_ALL | SI_NO_ACL_PROTECT | SI_PAGE_TITLE;
|
||
|
pObjectInfo->hInstance = g_hInstanceSave;
|
||
|
pObjectInfo->pszServerName = QueryMachineName();
|
||
|
pObjectInfo->pszObjectName = QueryShareName();
|
||
|
pObjectInfo->pszPageTitle = QueryPageTitle();
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
typedef enum _AcluiApiIndex
|
||
|
{
|
||
|
ACLUI_CREATE_PAGE = 0
|
||
|
};
|
||
|
|
||
|
// not subject to localization
|
||
|
static LPCSTR g_apchFunctionNames[] = {
|
||
|
"CreateSecurityPage",
|
||
|
NULL
|
||
|
};
|
||
|
|
||
|
// not subject to localization
|
||
|
DynamicDLL g_AcluiDLL( _T("ACLUI.DLL"), g_apchFunctionNames );
|
||
|
|
||
|
/*
|
||
|
HPROPSHEETPAGE ACLUIAPI CreateSecurityPage( LPSECURITYINFO psi );
|
||
|
*/
|
||
|
typedef HPROPSHEETPAGE (*CREATEPAGE_PROC) (LPSECURITYINFO);
|
||
|
|
||
|
HRESULT
|
||
|
MyCreateShareSecurityPage(
|
||
|
IN LPPROPERTYSHEETCALLBACK pCallBack,
|
||
|
IN CShareSecurityInformation *pSecInfo,
|
||
|
IN LPCTSTR pszMachineName,
|
||
|
IN LPCTSTR pszShareName
|
||
|
)
|
||
|
{
|
||
|
ASSERT( pCallBack );
|
||
|
ASSERT( pSecInfo );
|
||
|
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
if ( !g_AcluiDLL.LoadFunctionPointers() )
|
||
|
return hr; // ignore the load failure
|
||
|
|
||
|
pSecInfo->SetMachineName( pszMachineName );
|
||
|
pSecInfo->SetShareName( pszShareName );
|
||
|
CString csPageTitle;
|
||
|
csPageTitle.LoadString(IDS_SHARE_SECURITY);
|
||
|
pSecInfo->SetPageTitle( csPageTitle );
|
||
|
|
||
|
pSecInfo->AddRef();
|
||
|
|
||
|
HPROPSHEETPAGE hPage = ((CREATEPAGE_PROC)g_AcluiDLL[ACLUI_CREATE_PAGE])(pSecInfo);
|
||
|
if (hPage)
|
||
|
pCallBack->AddPage(hPage);
|
||
|
else
|
||
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
||
|
|
||
|
pSecInfo->Release();
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
CSecurityInformation::NewDefaultDescriptor(
|
||
|
OUT PSECURITY_DESCRIPTOR *ppsd,
|
||
|
IN SECURITY_INFORMATION /*RequestedInformation*/
|
||
|
)
|
||
|
{
|
||
|
ASSERT(ppsd);
|
||
|
|
||
|
*ppsd = NULL;
|
||
|
|
||
|
PSID psidWorld = NULL, psidAdmins = NULL;
|
||
|
PACL pAcl = NULL;
|
||
|
SECURITY_DESCRIPTOR sd;
|
||
|
DWORD dwErr = 0;
|
||
|
|
||
|
do { // false loop
|
||
|
|
||
|
// get World SID for "everyone"
|
||
|
SID_IDENTIFIER_AUTHORITY IDAuthorityWorld = SECURITY_WORLD_SID_AUTHORITY;
|
||
|
if ( !::AllocateAndInitializeSid(
|
||
|
&IDAuthorityWorld,
|
||
|
1,
|
||
|
SECURITY_WORLD_RID,
|
||
|
0,0,0,0,0,0,0,
|
||
|
&psidWorld ) )
|
||
|
{
|
||
|
dwErr = GetLastError();
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// get Admins SID
|
||
|
SID_IDENTIFIER_AUTHORITY IDAuthorityNT = SECURITY_NT_AUTHORITY;
|
||
|
if ( !::AllocateAndInitializeSid(
|
||
|
&IDAuthorityNT,
|
||
|
2,
|
||
|
SECURITY_BUILTIN_DOMAIN_RID,
|
||
|
DOMAIN_ALIAS_RID_ADMINS,
|
||
|
0,0,0,0,0,0,
|
||
|
&psidAdmins ) )
|
||
|
{
|
||
|
dwErr = GetLastError();
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// build ACL, and add AccessAllowedAce to it
|
||
|
DWORD cbAcl = sizeof (ACL) + sizeof (ACCESS_ALLOWED_ACE) +
|
||
|
::GetLengthSid(psidWorld) - sizeof (DWORD);
|
||
|
pAcl = reinterpret_cast<ACL *>(LocalAlloc(LPTR, cbAcl));
|
||
|
if ( !pAcl ||
|
||
|
!::InitializeAcl(pAcl, cbAcl, ACL_REVISION2) ||
|
||
|
!::AddAccessAllowedAce(pAcl, ACL_REVISION2, GENERIC_ALL, psidWorld) )
|
||
|
{
|
||
|
dwErr = GetLastError();
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// add ACL to the security descriptor, and set Owner and Group appropriately
|
||
|
if ( !::InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION) ||
|
||
|
!::SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE) ||
|
||
|
!::SetSecurityDescriptorOwner(&sd, psidAdmins, FALSE) ||
|
||
|
!::SetSecurityDescriptorGroup(&sd, psidAdmins, FALSE) )
|
||
|
{
|
||
|
dwErr = GetLastError();
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// convert security descriptor to self-relative format
|
||
|
DWORD cbSD = 0;
|
||
|
::MakeSelfRelativeSD(&sd, NULL, &cbSD); // this call should fail and set cbSD to the correct size
|
||
|
*ppsd = (PSECURITY_DESCRIPTOR)(LocalAlloc(LPTR, cbSD));
|
||
|
if ( !(*ppsd) || !::MakeSelfRelativeSD(&sd, *ppsd, &cbSD) )
|
||
|
{
|
||
|
dwErr = GetLastError();
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
} while (FALSE); // false loop
|
||
|
|
||
|
// clean up
|
||
|
if (psidWorld)
|
||
|
(void)::FreeSid(psidWorld);
|
||
|
if (psidAdmins)
|
||
|
(void)::FreeSid(psidAdmins);
|
||
|
|
||
|
if (pAcl)
|
||
|
LocalFree(pAcl);
|
||
|
|
||
|
if (dwErr && *ppsd)
|
||
|
{
|
||
|
LocalFree(*ppsd);
|
||
|
*ppsd = NULL;
|
||
|
}
|
||
|
|
||
|
return (dwErr ? HRESULT_FROM_WIN32(dwErr) : S_OK);
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
CSecurityInformation::MakeSelfRelativeCopy(
|
||
|
IN PSECURITY_DESCRIPTOR psdOriginal,
|
||
|
OUT PSECURITY_DESCRIPTOR *ppsdNew
|
||
|
)
|
||
|
{
|
||
|
ASSERT(psdOriginal);
|
||
|
ASSERT(ppsdNew);
|
||
|
|
||
|
*ppsdNew = NULL;
|
||
|
|
||
|
DWORD dwErr = 0;
|
||
|
PSECURITY_DESCRIPTOR psdSelfRelative = NULL;
|
||
|
|
||
|
do { // false loop
|
||
|
|
||
|
DWORD cbSD = ::GetSecurityDescriptorLength(psdOriginal);
|
||
|
psdSelfRelative = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, cbSD);
|
||
|
if ( !psdSelfRelative )
|
||
|
{
|
||
|
dwErr = ::GetLastError();
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// we have to find out whether the original is already self-relative
|
||
|
SECURITY_DESCRIPTOR_CONTROL sdc = 0;
|
||
|
DWORD dwRevision = 0;
|
||
|
if ( !::GetSecurityDescriptorControl(psdOriginal, &sdc, &dwRevision) )
|
||
|
{
|
||
|
dwErr = ::GetLastError();
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (sdc & SE_SELF_RELATIVE)
|
||
|
{
|
||
|
::memcpy(psdSelfRelative, psdOriginal, cbSD);
|
||
|
} else if ( !::MakeSelfRelativeSD(psdOriginal, psdSelfRelative, &cbSD) )
|
||
|
{
|
||
|
dwErr = ::GetLastError();
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
*ppsdNew = psdSelfRelative;
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
if (dwErr && psdSelfRelative)
|
||
|
LocalFree(psdSelfRelative);
|
||
|
|
||
|
return (dwErr ? HRESULT_FROM_WIN32(dwErr) : S_OK);
|
||
|
}
|