mirror of
https://github.com/reactos/reactos.git
synced 2024-08-26 13:18:51 +00:00
951 lines
32 KiB
C
951 lines
32 KiB
C
/*
|
|
* Regedit ACL Editor for Registry Keys
|
|
*
|
|
* Copyright (C) 2004 - 2006 Thomas Weidenmueller <w3seek@reactos.com>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include "regedit.h"
|
|
|
|
#define INITGUID
|
|
#include <guiddef.h>
|
|
|
|
/* FIXME - shouldn't be defined here... */
|
|
DEFINE_GUID(IID_IRegKeySecurity, 0x965fc360, 0x16ff, 0x11d0, 0x0091, 0xcb,0x00,0xaa,0x00,0xbb,0xb7,0x23);
|
|
#if REGEDIT_IMPLEMENT_ISECURITYINFORMATION2
|
|
DEFINE_GUID(IID_IRegKeySecurity2, 0xc3ccfdb4, 0x6f88, 0x11d2, 0x00a3, 0xce,0x00,0xc0,0x4f,0xb1,0x78,0x2a);
|
|
#endif
|
|
|
|
/* FIXME: already defined in aclui.h - causing problems when compiling with MSVC/PSDK*/
|
|
#ifdef _MSC_VER
|
|
#pragma message ("INVESTIGATE ME")
|
|
#endif
|
|
|
|
#if 1 //#ifndef _MSC_VER
|
|
DEFINE_GUID(IID_IEffectivePermission, 0x3853dc76, 0x9f35, 0x407c, 0x0088, 0xa1,0xd1,0x93,0x44,0x36,0x5f,0xbc);
|
|
DEFINE_GUID(IID_ISecurityObjectTypeInfo, 0xfc3066eb, 0x79ef, 0x444b, 0x0091, 0x11,0xd1,0x8a,0x75,0xeb,0xf2,0xfa);
|
|
#endif
|
|
|
|
/******************************************************************************
|
|
Implementation of the IUnknown methods of CRegKeySecurity
|
|
******************************************************************************/
|
|
|
|
static __inline PCRegKeySecurity
|
|
impl_from_ISecurityInformation(struct ISecurityInformation *iface)
|
|
{
|
|
return (PCRegKeySecurity)((ULONG_PTR)iface - FIELD_OFFSET(CRegKeySecurity,
|
|
lpISecurityInformationVtbl));
|
|
}
|
|
|
|
#if REGEDIT_IMPLEMENT_ISECURITYINFORMATION2
|
|
static __inline PCRegKeySecurity
|
|
impl_from_ISecurityInformation2(struct ISecurityInformation2 *iface)
|
|
{
|
|
return (PCRegKeySecurity)((ULONG_PTR)iface - FIELD_OFFSET(CRegKeySecurity,
|
|
lpISecurityInformation2Vtbl));
|
|
}
|
|
#endif
|
|
|
|
static __inline PCRegKeySecurity
|
|
impl_from_ISecurityObjectTypeInfo(struct ISecurityObjectTypeInfo *iface)
|
|
{
|
|
return (PCRegKeySecurity)((ULONG_PTR)iface - FIELD_OFFSET(CRegKeySecurity,
|
|
lpISecurityObjectTypeInfoVtbl));
|
|
}
|
|
|
|
static __inline PCRegKeySecurity
|
|
impl_from_IEffectivePermission(struct IEffectivePermission *iface)
|
|
{
|
|
return (PCRegKeySecurity)((ULONG_PTR)iface - FIELD_OFFSET(CRegKeySecurity,
|
|
lpIEffectivePermissionVtbl));
|
|
}
|
|
|
|
#define impl_to_interface(impl,iface) (struct iface *)(&(impl)->lp##iface##Vtbl)
|
|
|
|
static __inline ULONG
|
|
CRegKeySecurity_fnAddRef(PCRegKeySecurity obj)
|
|
{
|
|
return (ULONG)InterlockedIncrement((LONG*)&obj->ref);
|
|
}
|
|
|
|
static __inline ULONG
|
|
CRegKeySecurity_fnRelease(PCRegKeySecurity obj)
|
|
{
|
|
ULONG Ret;
|
|
|
|
Ret = (ULONG)InterlockedDecrement((LONG*)&obj->ref);
|
|
if (Ret == 0)
|
|
{
|
|
HeapFree(GetProcessHeap(),
|
|
0,
|
|
obj);
|
|
}
|
|
|
|
return Ret;
|
|
}
|
|
|
|
static __inline HRESULT
|
|
CRegKeySecurity_fnQueryInterface(PCRegKeySecurity obj,
|
|
REFIID iid,
|
|
PVOID *pvObject)
|
|
{
|
|
PVOID pvObj = NULL;
|
|
|
|
if (IsEqualGUID(iid,
|
|
&IID_IRegKeySecurity))
|
|
{
|
|
pvObj = (PVOID)impl_to_interface(obj,
|
|
ISecurityInformation);
|
|
}
|
|
#if REGEDIT_IMPLEMENT_ISECURITYINFORMATION2
|
|
else if (IsEqualGUID(iid,
|
|
&IID_IRegKeySecurity2))
|
|
{
|
|
pvObj = (PVOID)impl_to_interface(obj,
|
|
ISecurityInformation2);
|
|
}
|
|
#endif
|
|
else if (IsEqualGUID(iid,
|
|
&IID_IEffectivePermission))
|
|
{
|
|
pvObj = (PVOID)impl_to_interface(obj,
|
|
IEffectivePermission);
|
|
}
|
|
else if (IsEqualGUID(iid,
|
|
&IID_ISecurityObjectTypeInfo))
|
|
{
|
|
pvObj = (PVOID)impl_to_interface(obj,
|
|
ISecurityObjectTypeInfo);
|
|
}
|
|
|
|
if (pvObj == NULL)
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
*pvObject = pvObj;
|
|
CRegKeySecurity_fnAddRef(obj);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
Definition of the ISecurityInformation interface
|
|
******************************************************************************/
|
|
|
|
/* IUnknown */
|
|
static HRESULT STDMETHODCALLTYPE
|
|
ISecurityInformation_fnQueryInterface(struct ISecurityInformation *this,
|
|
REFIID iid,
|
|
PVOID *pvObject);
|
|
|
|
static ULONG STDMETHODCALLTYPE
|
|
ISecurityInformation_fnAddRef(struct ISecurityInformation *this);
|
|
|
|
static ULONG STDMETHODCALLTYPE
|
|
ISecurityInformation_fnRelease(struct ISecurityInformation *this);
|
|
|
|
/* ISecurityInformation */
|
|
static HRESULT STDMETHODCALLTYPE
|
|
ISecurityInformation_fnGetObjectInformation(struct ISecurityInformation *this,
|
|
PSI_OBJECT_INFO pObjectInfo);
|
|
|
|
static HRESULT STDMETHODCALLTYPE
|
|
ISecurityInformation_fnGetSecurity(struct ISecurityInformation *this,
|
|
SECURITY_INFORMATION RequestedInformation,
|
|
PSECURITY_DESCRIPTOR* ppSecurityDescriptor,
|
|
BOOL fDefault);
|
|
|
|
static HRESULT STDMETHODCALLTYPE
|
|
ISecurityInformation_fnSetSecurity(struct ISecurityInformation *this,
|
|
SECURITY_INFORMATION RequestedInformation,
|
|
PSECURITY_DESCRIPTOR pSecurityDescriptor);
|
|
|
|
static HRESULT STDMETHODCALLTYPE
|
|
ISecurityInformation_fnGetAccessRights(struct ISecurityInformation *this,
|
|
const GUID* pguidObjectType,
|
|
DWORD dwFlags,
|
|
PSI_ACCESS* ppAccess,
|
|
ULONG* pcAccesses,
|
|
ULONG* piDefaultAccess);
|
|
|
|
static HRESULT STDMETHODCALLTYPE
|
|
ISecurityInformation_fnMapGeneric(struct ISecurityInformation *this,
|
|
const GUID* pguidObjectType,
|
|
UCHAR* pAceFlags,
|
|
ACCESS_MASK* pMask);
|
|
|
|
static HRESULT STDMETHODCALLTYPE
|
|
ISecurityInformation_fnGetInheritTypes(struct ISecurityInformation *this,
|
|
PSI_INHERIT_TYPE* ppInheritTypes,
|
|
ULONG* pcInheritTypes);
|
|
static HRESULT STDMETHODCALLTYPE
|
|
ISecurityInformation_fnPropertySheetPageCallback(struct ISecurityInformation *this,
|
|
HWND hwnd,
|
|
UINT uMsg,
|
|
SI_PAGE_TYPE uPage);
|
|
|
|
static const struct ifaceISecurityInformationVbtl vtblISecurityInformation =
|
|
{
|
|
/* IUnknown methods */
|
|
ISecurityInformation_fnQueryInterface,
|
|
ISecurityInformation_fnAddRef,
|
|
ISecurityInformation_fnRelease,
|
|
|
|
/* ISecurityInformation methods */
|
|
ISecurityInformation_fnGetObjectInformation,
|
|
ISecurityInformation_fnGetSecurity,
|
|
ISecurityInformation_fnSetSecurity,
|
|
ISecurityInformation_fnGetAccessRights,
|
|
ISecurityInformation_fnMapGeneric,
|
|
ISecurityInformation_fnGetInheritTypes,
|
|
ISecurityInformation_fnPropertySheetPageCallback,
|
|
};
|
|
|
|
#if REGEDIT_IMPLEMENT_ISECURITYINFORMATION2
|
|
/******************************************************************************
|
|
Definition of the ISecurityInformation2 interface
|
|
******************************************************************************/
|
|
|
|
/* IUnknown */
|
|
static HRESULT STDMETHODCALLTYPE
|
|
ISecurityInformation2_fnQueryInterface(struct ISecurityInformation2 *this,
|
|
REFIID iid,
|
|
PVOID *pvObject);
|
|
|
|
static ULONG STDMETHODCALLTYPE
|
|
ISecurityInformation2_fnAddRef(struct ISecurityInformation2 *this);
|
|
|
|
static ULONG STDMETHODCALLTYPE
|
|
ISecurityInformation2_fnRelease(struct ISecurityInformation2 *this);
|
|
|
|
/* ISecurityInformation2 */
|
|
static BOOL STDMETHODCALLTYPE
|
|
ISecurityInformation2_fnIsDaclCanonical(struct ISecurityInformation2 *this,
|
|
PACL pDacl);
|
|
|
|
static HRESULT STDMETHODCALLTYPE
|
|
ISecurityInformation2_fnLookupSids(struct ISecurityInformation2 *this,
|
|
ULONG cSids,
|
|
PSID* rgpSids,
|
|
LPDATAOBJECT* ppdo);
|
|
|
|
static const struct ifaceISecurityInformation2Vbtl vtblISecurityInformation2 =
|
|
{
|
|
/* IUnknown methods */
|
|
ISecurityInformation2_fnQueryInterface,
|
|
ISecurityInformation2_fnAddRef,
|
|
ISecurityInformation2_fnRelease,
|
|
|
|
/* ISecurityInformation2 methods */
|
|
ISecurityInformation2_fnIsDaclCanonical,
|
|
ISecurityInformation2_fnLookupSids
|
|
};
|
|
#endif
|
|
|
|
/******************************************************************************
|
|
Definition of the IEffectivePermission interface
|
|
******************************************************************************/
|
|
|
|
/* IUnknown */
|
|
static HRESULT STDMETHODCALLTYPE
|
|
IEffectivePermission_fnQueryInterface(struct IEffectivePermission *this,
|
|
REFIID iid,
|
|
PVOID *pvObject);
|
|
|
|
static ULONG STDMETHODCALLTYPE
|
|
IEffectivePermission_fnAddRef(struct IEffectivePermission *this);
|
|
|
|
static ULONG STDMETHODCALLTYPE
|
|
IEffectivePermission_fnRelease(struct IEffectivePermission *this);
|
|
|
|
/* IEffectivePermission */
|
|
static HRESULT STDMETHODCALLTYPE
|
|
IEffectivePermission_fnGetEffectivePermission(struct IEffectivePermission *this,
|
|
const GUID* pguidObjectType,
|
|
PSID pUserSid,
|
|
LPCWSTR pszServerName,
|
|
PSECURITY_DESCRIPTOR pSD,
|
|
POBJECT_TYPE_LIST* ppObjectTypeList,
|
|
ULONG* pcObjectTypeListLength,
|
|
PACCESS_MASK* ppGrantedAccessList,
|
|
ULONG* pcGrantedAccessListLength);
|
|
|
|
static const struct ifaceIEffectivePermissionVbtl vtblIEffectivePermission =
|
|
{
|
|
/* IUnknown methods */
|
|
IEffectivePermission_fnQueryInterface,
|
|
IEffectivePermission_fnAddRef,
|
|
IEffectivePermission_fnRelease,
|
|
|
|
/* IEffectivePermissions methods */
|
|
IEffectivePermission_fnGetEffectivePermission
|
|
};
|
|
|
|
/******************************************************************************
|
|
Definition of the ISecurityObjectTypeInfo interface
|
|
******************************************************************************/
|
|
|
|
/* IUnknown */
|
|
static HRESULT STDMETHODCALLTYPE
|
|
ISecurityObjectTypeInfo_fnQueryInterface(struct ISecurityObjectTypeInfo *this,
|
|
REFIID iid,
|
|
PVOID *pvObject);
|
|
|
|
static ULONG STDMETHODCALLTYPE
|
|
ISecurityObjectTypeInfo_fnAddRef(struct ISecurityObjectTypeInfo *this);
|
|
|
|
static ULONG STDMETHODCALLTYPE
|
|
ISecurityObjectTypeInfo_fnRelease(struct ISecurityObjectTypeInfo *this);
|
|
|
|
/* ISecurityObjectTypeInfo */
|
|
static HRESULT STDMETHODCALLTYPE
|
|
ISecurityObjectTypeInfo_fnGetInheritSource(struct ISecurityObjectTypeInfo *this,
|
|
SECURITY_INFORMATION si,
|
|
PACL pACL,
|
|
PINHERITED_FROM* ppInheritArray);
|
|
|
|
static const struct ifaceISecurityObjectTypeInfoVbtl vtblISecurityObjectTypeInfo =
|
|
{
|
|
/* IUnknown methods */
|
|
ISecurityObjectTypeInfo_fnQueryInterface,
|
|
ISecurityObjectTypeInfo_fnAddRef,
|
|
ISecurityObjectTypeInfo_fnRelease,
|
|
|
|
/* ISecurityObjectTypeInfo methods */
|
|
ISecurityObjectTypeInfo_fnGetInheritSource
|
|
};
|
|
|
|
|
|
/******************************************************************************
|
|
Implementation of the ISecurityInformation interface
|
|
******************************************************************************/
|
|
|
|
static SI_ACCESS RegAccess[] = {
|
|
{&GUID_NULL, KEY_ALL_ACCESS, MAKEINTRESOURCEW(IDS_ACCESS_FULLCONTROL), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC},
|
|
{&GUID_NULL, KEY_READ, MAKEINTRESOURCEW(IDS_ACCESS_READ), SI_ACCESS_GENERAL},
|
|
{&GUID_NULL, KEY_QUERY_VALUE, MAKEINTRESOURCEW(IDS_ACCESS_QUERYVALUE), SI_ACCESS_SPECIFIC},
|
|
{&GUID_NULL, KEY_SET_VALUE, MAKEINTRESOURCEW(IDS_ACCESS_SETVALUE), SI_ACCESS_SPECIFIC},
|
|
{&GUID_NULL, KEY_CREATE_SUB_KEY, MAKEINTRESOURCEW(IDS_ACCESS_CREATESUBKEY), SI_ACCESS_SPECIFIC},
|
|
{&GUID_NULL, KEY_ENUMERATE_SUB_KEYS, MAKEINTRESOURCEW(IDS_ACCESS_ENUMERATESUBKEYS), SI_ACCESS_SPECIFIC},
|
|
{&GUID_NULL, KEY_NOTIFY, MAKEINTRESOURCEW(IDS_ACCESS_NOTIFY), SI_ACCESS_SPECIFIC},
|
|
{&GUID_NULL, KEY_CREATE_LINK, MAKEINTRESOURCEW(IDS_ACCESS_CREATELINK), SI_ACCESS_SPECIFIC},
|
|
{&GUID_NULL, DELETE, MAKEINTRESOURCEW(IDS_ACCESS_DELETE), SI_ACCESS_SPECIFIC},
|
|
{&GUID_NULL, WRITE_DAC, MAKEINTRESOURCEW(IDS_ACCESS_WRITEDAC), SI_ACCESS_SPECIFIC},
|
|
{&GUID_NULL, WRITE_OWNER, MAKEINTRESOURCEW(IDS_ACCESS_WRITEOWNER), SI_ACCESS_SPECIFIC},
|
|
{&GUID_NULL, READ_CONTROL, MAKEINTRESOURCEW(IDS_ACCESS_READCONTROL), SI_ACCESS_SPECIFIC},
|
|
};
|
|
|
|
static const DWORD RegDefaultAccess = 1; /* KEY_READ */
|
|
|
|
static GENERIC_MAPPING RegAccessMasks = {
|
|
KEY_READ,
|
|
KEY_WRITE,
|
|
KEY_EXECUTE,
|
|
KEY_ALL_ACCESS
|
|
};
|
|
|
|
static SI_INHERIT_TYPE RegInheritTypes[] = {
|
|
{&GUID_NULL, 0, (LPWSTR)MAKEINTRESOURCEW(IDS_INHERIT_THISKEYONLY)},
|
|
{&GUID_NULL, CONTAINER_INHERIT_ACE, (LPWSTR)MAKEINTRESOURCEW(IDS_INHERIT_THISKEYANDSUBKEYS)},
|
|
{&GUID_NULL, INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE, (LPWSTR)MAKEINTRESOURCEW(IDS_INHERIT_SUBKEYSONLY)},
|
|
};
|
|
|
|
static HRESULT STDMETHODCALLTYPE
|
|
ISecurityInformation_fnQueryInterface(struct ISecurityInformation *this,
|
|
REFIID iid,
|
|
PVOID *pvObject)
|
|
{
|
|
if (IsEqualGUID(iid,
|
|
&IID_IUnknown))
|
|
{
|
|
*pvObject = (PVOID)this;
|
|
ISecurityInformation_fnAddRef(this);
|
|
return S_OK;
|
|
}
|
|
|
|
return CRegKeySecurity_fnQueryInterface(impl_from_ISecurityInformation(this),
|
|
iid,
|
|
pvObject);
|
|
}
|
|
|
|
static ULONG STDMETHODCALLTYPE
|
|
ISecurityInformation_fnAddRef(struct ISecurityInformation *this)
|
|
{
|
|
return CRegKeySecurity_fnAddRef(impl_from_ISecurityInformation(this));
|
|
}
|
|
|
|
static ULONG STDMETHODCALLTYPE
|
|
ISecurityInformation_fnRelease(struct ISecurityInformation *this)
|
|
{
|
|
return CRegKeySecurity_fnRelease(impl_from_ISecurityInformation(this));
|
|
}
|
|
|
|
static HRESULT STDMETHODCALLTYPE
|
|
ISecurityInformation_fnGetObjectInformation(struct ISecurityInformation *this,
|
|
PSI_OBJECT_INFO pObjectInfo)
|
|
{
|
|
PCRegKeySecurity obj = impl_from_ISecurityInformation(this);
|
|
|
|
*pObjectInfo = obj->ObjectInfo;
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT STDMETHODCALLTYPE
|
|
ISecurityInformation_fnGetSecurity(struct ISecurityInformation *this,
|
|
SECURITY_INFORMATION RequestedInformation,
|
|
PSECURITY_DESCRIPTOR* ppSecurityDescriptor,
|
|
BOOL fDefault)
|
|
{
|
|
PCRegKeySecurity obj = impl_from_ISecurityInformation(this);
|
|
LONG ErrorCode;
|
|
|
|
ErrorCode = GetNamedSecurityInfoW(obj->szRegKey,
|
|
SE_REGISTRY_KEY,
|
|
RequestedInformation,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
ppSecurityDescriptor);
|
|
|
|
return HRESULT_FROM_WIN32(ErrorCode);
|
|
}
|
|
|
|
static HRESULT STDMETHODCALLTYPE
|
|
ISecurityInformation_fnSetSecurity(struct ISecurityInformation *this,
|
|
SECURITY_INFORMATION RequestedInformation,
|
|
PSECURITY_DESCRIPTOR pSecurityDescriptor)
|
|
{
|
|
PCRegKeySecurity obj = impl_from_ISecurityInformation(this);
|
|
|
|
/* FIXME */
|
|
*obj->Btn = TRUE;
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT STDMETHODCALLTYPE
|
|
ISecurityInformation_fnGetAccessRights(struct ISecurityInformation *this,
|
|
const GUID* pguidObjectType,
|
|
DWORD dwFlags,
|
|
PSI_ACCESS* ppAccess,
|
|
ULONG* pcAccesses,
|
|
ULONG* piDefaultAccess)
|
|
{
|
|
*ppAccess = RegAccess;
|
|
*pcAccesses = COUNT_OF(RegAccess);
|
|
*piDefaultAccess = RegDefaultAccess;
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT STDMETHODCALLTYPE
|
|
ISecurityInformation_fnMapGeneric(struct ISecurityInformation *this,
|
|
const GUID* pguidObjectType,
|
|
UCHAR* pAceFlags,
|
|
ACCESS_MASK* pMask)
|
|
{
|
|
MapGenericMask(pMask,
|
|
&RegAccessMasks);
|
|
*pMask &= ~SYNCHRONIZE;
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT STDMETHODCALLTYPE
|
|
ISecurityInformation_fnGetInheritTypes(struct ISecurityInformation *this,
|
|
PSI_INHERIT_TYPE* ppInheritTypes,
|
|
ULONG* pcInheritTypes)
|
|
{
|
|
PCRegKeySecurity obj = impl_from_ISecurityInformation(this);
|
|
|
|
/* FIXME */
|
|
if (obj->ObjectInfo.dwFlags & SI_CONTAINER)
|
|
{
|
|
*ppInheritTypes = RegInheritTypes;
|
|
*pcInheritTypes = COUNT_OF(RegInheritTypes);
|
|
return S_OK;
|
|
}
|
|
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT STDMETHODCALLTYPE
|
|
ISecurityInformation_fnPropertySheetPageCallback(struct ISecurityInformation *this,
|
|
HWND hwnd,
|
|
UINT uMsg,
|
|
SI_PAGE_TYPE uPage)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
#if REGEDIT_IMPLEMENT_ISECURITYINFORMATION2
|
|
/******************************************************************************
|
|
Implementation of the ISecurityInformation2 interface
|
|
******************************************************************************/
|
|
|
|
static HRESULT STDMETHODCALLTYPE
|
|
ISecurityInformation2_fnQueryInterface(struct ISecurityInformation2 *this,
|
|
REFIID iid,
|
|
PVOID *pvObject)
|
|
{
|
|
if (IsEqualGUID(iid,
|
|
&IID_IUnknown))
|
|
{
|
|
*pvObject = (PVOID)this;
|
|
ISecurityInformation2_fnAddRef(this);
|
|
return S_OK;
|
|
}
|
|
|
|
return CRegKeySecurity_fnQueryInterface(impl_from_ISecurityInformation2(this),
|
|
iid,
|
|
pvObject);
|
|
}
|
|
|
|
static ULONG STDMETHODCALLTYPE
|
|
ISecurityInformation2_fnAddRef(struct ISecurityInformation2 *this)
|
|
{
|
|
return CRegKeySecurity_fnAddRef(impl_from_ISecurityInformation2(this));
|
|
}
|
|
|
|
static ULONG STDMETHODCALLTYPE
|
|
ISecurityInformation2_fnRelease(struct ISecurityInformation2 *this)
|
|
{
|
|
return CRegKeySecurity_fnRelease(impl_from_ISecurityInformation2(this));
|
|
}
|
|
|
|
static BOOL STDMETHODCALLTYPE
|
|
ISecurityInformation2_fnIsDaclCanonical(struct ISecurityInformation2 *this,
|
|
PACL pDacl)
|
|
{
|
|
/* FIXME */
|
|
return TRUE;
|
|
}
|
|
|
|
static HRESULT STDMETHODCALLTYPE
|
|
ISecurityInformation2_fnLookupSids(struct ISecurityInformation2 *this,
|
|
ULONG cSids,
|
|
PSID* rgpSids,
|
|
LPDATAOBJECT* ppdo)
|
|
{
|
|
/* FIXME */
|
|
return E_NOTIMPL;
|
|
}
|
|
#endif
|
|
|
|
/******************************************************************************
|
|
Implementation of the IEffectivePermission interface
|
|
******************************************************************************/
|
|
|
|
static HRESULT STDMETHODCALLTYPE
|
|
IEffectivePermission_fnQueryInterface(struct IEffectivePermission *this,
|
|
REFIID iid,
|
|
PVOID *pvObject)
|
|
{
|
|
if (IsEqualGUID(iid,
|
|
&IID_IUnknown))
|
|
{
|
|
*pvObject = (PVOID)this;
|
|
IEffectivePermission_fnAddRef(this);
|
|
return S_OK;
|
|
}
|
|
|
|
return CRegKeySecurity_fnQueryInterface(impl_from_IEffectivePermission(this),
|
|
iid,
|
|
pvObject);
|
|
}
|
|
|
|
static ULONG STDMETHODCALLTYPE
|
|
IEffectivePermission_fnAddRef(struct IEffectivePermission *this)
|
|
{
|
|
return CRegKeySecurity_fnAddRef(impl_from_IEffectivePermission(this));
|
|
}
|
|
|
|
static ULONG STDMETHODCALLTYPE
|
|
IEffectivePermission_fnRelease(struct IEffectivePermission *this)
|
|
{
|
|
return CRegKeySecurity_fnRelease(impl_from_IEffectivePermission(this));
|
|
}
|
|
|
|
static HRESULT STDMETHODCALLTYPE
|
|
IEffectivePermission_fnGetEffectivePermission(struct IEffectivePermission *this,
|
|
const GUID* pguidObjectType,
|
|
PSID pUserSid,
|
|
LPCWSTR pszServerName,
|
|
PSECURITY_DESCRIPTOR pSD,
|
|
POBJECT_TYPE_LIST* ppObjectTypeList,
|
|
ULONG* pcObjectTypeListLength,
|
|
PACCESS_MASK* ppGrantedAccessList,
|
|
ULONG* pcGrantedAccessListLength)
|
|
{
|
|
PACL Dacl = NULL;
|
|
BOOL DaclPresent, DaclDefaulted;
|
|
PACCESS_MASK GrantedAccessList;
|
|
DWORD ErrorCode = ERROR_SUCCESS;
|
|
TRUSTEE Trustee = {0};
|
|
static OBJECT_TYPE_LIST DefObjTypeList = {0};
|
|
|
|
*ppObjectTypeList = &DefObjTypeList;
|
|
*pcObjectTypeListLength = 1;
|
|
|
|
BuildTrusteeWithSid(&Trustee,
|
|
pUserSid);
|
|
|
|
if (GetSecurityDescriptorDacl(pSD,
|
|
&DaclPresent,
|
|
&Dacl,
|
|
&DaclDefaulted) && DaclPresent)
|
|
{
|
|
GrantedAccessList = (PACCESS_MASK)LocalAlloc(LMEM_FIXED,
|
|
sizeof(ACCESS_MASK));
|
|
if (GrantedAccessList == NULL)
|
|
{
|
|
goto Fail;
|
|
}
|
|
|
|
ErrorCode = GetEffectiveRightsFromAcl(Dacl,
|
|
&Trustee,
|
|
GrantedAccessList);
|
|
if (ErrorCode == ERROR_SUCCESS)
|
|
{
|
|
*ppGrantedAccessList = GrantedAccessList;
|
|
*pcGrantedAccessListLength = 1;
|
|
}
|
|
else
|
|
LocalFree((HLOCAL)GrantedAccessList);
|
|
}
|
|
else
|
|
Fail:
|
|
ErrorCode = GetLastError();
|
|
|
|
return HRESULT_FROM_WIN32(ErrorCode);
|
|
}
|
|
|
|
/******************************************************************************
|
|
Implementation of the ISecurityObjectTypeInfo interface
|
|
******************************************************************************/
|
|
|
|
static HRESULT STDMETHODCALLTYPE
|
|
ISecurityObjectTypeInfo_fnQueryInterface(struct ISecurityObjectTypeInfo *this,
|
|
REFIID iid,
|
|
PVOID *pvObject)
|
|
{
|
|
if (IsEqualGUID(iid,
|
|
&IID_IUnknown))
|
|
{
|
|
*pvObject = (PVOID)this;
|
|
ISecurityObjectTypeInfo_fnAddRef(this);
|
|
return S_OK;
|
|
}
|
|
|
|
return CRegKeySecurity_fnQueryInterface(impl_from_ISecurityObjectTypeInfo(this),
|
|
iid,
|
|
pvObject);
|
|
}
|
|
|
|
static ULONG STDMETHODCALLTYPE
|
|
ISecurityObjectTypeInfo_fnAddRef(struct ISecurityObjectTypeInfo *this)
|
|
{
|
|
return CRegKeySecurity_fnAddRef(impl_from_ISecurityObjectTypeInfo(this));
|
|
}
|
|
|
|
static ULONG STDMETHODCALLTYPE
|
|
ISecurityObjectTypeInfo_fnRelease(struct ISecurityObjectTypeInfo *this)
|
|
{
|
|
return CRegKeySecurity_fnRelease(impl_from_ISecurityObjectTypeInfo(this));
|
|
}
|
|
|
|
static HRESULT STDMETHODCALLTYPE
|
|
ISecurityObjectTypeInfo_fnGetInheritSource(struct ISecurityObjectTypeInfo *this,
|
|
SECURITY_INFORMATION si,
|
|
PACL pACL,
|
|
PINHERITED_FROM* ppInheritArray)
|
|
{
|
|
PCRegKeySecurity obj = impl_from_ISecurityObjectTypeInfo(this);
|
|
PINHERITED_FROM pif, pif2;
|
|
SIZE_T pifSize;
|
|
DWORD ErrorCode, i;
|
|
LPWSTR lpBuf;
|
|
|
|
pifSize = pACL->AceCount * sizeof(INHERITED_FROM);
|
|
pif = (PINHERITED_FROM)HeapAlloc(GetProcessHeap(),
|
|
0,
|
|
pifSize);
|
|
if (pif == NULL)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
ErrorCode = GetInheritanceSourceW(obj->szRegKey,
|
|
SE_REGISTRY_KEY,
|
|
si,
|
|
(obj->ObjectInfo.dwFlags & SI_CONTAINER) != 0,
|
|
NULL,
|
|
0,
|
|
pACL,
|
|
NULL,
|
|
&RegAccessMasks,
|
|
pif);
|
|
|
|
if (ErrorCode == ERROR_SUCCESS)
|
|
{
|
|
/* Calculate the size of the buffer to return */
|
|
for (i = 0;
|
|
i < pACL->AceCount;
|
|
i++)
|
|
{
|
|
if (pif[i].AncestorName != NULL)
|
|
{
|
|
pifSize += (wcslen(pif[i].AncestorName) + 1) * sizeof(WCHAR);
|
|
}
|
|
}
|
|
|
|
/* Allocate enough space for the array and the strings */
|
|
pif2 = (PINHERITED_FROM)LocalAlloc(LMEM_FIXED,
|
|
pifSize);
|
|
if (pif2 == NULL)
|
|
{
|
|
ErrorCode = GetLastError();
|
|
goto Cleanup;
|
|
}
|
|
|
|
/* copy the array and strings to the buffer */
|
|
lpBuf = (LPWSTR)((ULONG_PTR)pif2 + (pACL->AceCount * sizeof(INHERITED_FROM)));
|
|
for (i = 0;
|
|
i < pACL->AceCount;
|
|
i++)
|
|
{
|
|
pif2[i].GenerationGap = pif[i].GenerationGap;
|
|
if (pif[i].AncestorName != NULL)
|
|
{
|
|
pif2[i].AncestorName = lpBuf;
|
|
wcscpy(lpBuf,
|
|
pif[i].AncestorName);
|
|
lpBuf += wcslen(pif[i].AncestorName) + 1;
|
|
}
|
|
else
|
|
pif2[i].AncestorName = NULL;
|
|
}
|
|
|
|
/* return the newly allocated array */
|
|
*ppInheritArray = pif2;
|
|
}
|
|
|
|
Cleanup:
|
|
FreeInheritedFromArray(pif,
|
|
pACL->AceCount,
|
|
NULL);
|
|
HeapFree(GetProcessHeap(),
|
|
0,
|
|
pif);
|
|
|
|
return HRESULT_FROM_WIN32(ErrorCode);
|
|
}
|
|
|
|
/******************************************************************************
|
|
Implementation of the CRegKeySecurity constructor
|
|
******************************************************************************/
|
|
|
|
static PCRegKeySecurity
|
|
CRegKeySecurity_fnConstructor(LPWSTR lpRegKey,
|
|
HKEY hRootKey,
|
|
SI_OBJECT_INFO *ObjectInfo,
|
|
BOOL *Btn)
|
|
{
|
|
PCRegKeySecurity obj;
|
|
|
|
obj = (PCRegKeySecurity)HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
FIELD_OFFSET(CRegKeySecurity,
|
|
szRegKey[wcslen(lpRegKey) + 1]));
|
|
if (obj != NULL)
|
|
{
|
|
obj->ref = 1;
|
|
obj->lpISecurityInformationVtbl = &vtblISecurityInformation;
|
|
#if REGEDIT_IMPLEMENT_ISECURITYINFORMATION2
|
|
obj->lpISecurityInformation2Vtbl = &vtblISecurityInformation2;
|
|
#endif
|
|
obj->lpIEffectivePermissionVtbl = &vtblIEffectivePermission;
|
|
obj->lpISecurityObjectTypeInfoVtbl = &vtblISecurityObjectTypeInfo;
|
|
obj->ObjectInfo = *ObjectInfo;
|
|
obj->Btn = Btn;
|
|
obj->hRootKey = hRootKey;
|
|
wcscpy(obj->szRegKey,
|
|
lpRegKey);
|
|
}
|
|
else
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
return obj;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/******************************************************************************/
|
|
/******************************************************************************/
|
|
|
|
typedef struct _CHANGE_CONTEXT
|
|
{
|
|
HKEY hKey;
|
|
LPWSTR KeyString;
|
|
} CHANGE_CONTEXT, *PCHANGE_CONTEXT;
|
|
|
|
typedef BOOL (WINAPI *PEDITSECURITY)(HWND hwndOwner,
|
|
struct ISecurityInformation *psi);
|
|
|
|
static PEDITSECURITY pfnEditSecurity;
|
|
static HMODULE hAclUiDll;
|
|
|
|
BOOL
|
|
InitializeAclUiDll(VOID)
|
|
{
|
|
if (!(hAclUiDll = LoadLibraryW(L"aclui.dll")))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (!(pfnEditSecurity = (PEDITSECURITY)GetProcAddress(hAclUiDll,
|
|
"EditSecurity")))
|
|
{
|
|
FreeLibrary(hAclUiDll);
|
|
hAclUiDll = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
VOID
|
|
UnloadAclUiDll(VOID)
|
|
{
|
|
if (hAclUiDll != NULL)
|
|
{
|
|
FreeLibrary(hAclUiDll);
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
RegKeyEditPermissions(HWND hWndOwner,
|
|
HKEY hKey,
|
|
LPCWSTR lpMachine,
|
|
LPCWSTR lpKeyName)
|
|
{
|
|
BOOL Result = FALSE;
|
|
LPCWSTR lphKey = NULL;
|
|
LPWSTR lpKeyPath = NULL;
|
|
PCRegKeySecurity RegKeySecurity;
|
|
SI_OBJECT_INFO ObjectInfo;
|
|
size_t lnMachine = 0, lnKeyName = 0;
|
|
|
|
if (pfnEditSecurity == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (lpMachine != NULL)
|
|
lnMachine = wcslen(lpMachine);
|
|
if (lpKeyName != NULL)
|
|
lnKeyName = wcslen(lpKeyName);
|
|
|
|
/* build registry path */
|
|
if (lpMachine != NULL &&
|
|
(lpMachine[0] == L'\0' ||
|
|
(lpMachine[0] == L'.' && lpMachine[1] == L'.')))
|
|
{
|
|
lnMachine = 0;
|
|
}
|
|
|
|
if (hKey == HKEY_CLASSES_ROOT)
|
|
lphKey = L"CLASSES_ROOT";
|
|
else if (hKey == HKEY_CURRENT_USER)
|
|
lphKey = L"CURRENT_USER";
|
|
else if (hKey == HKEY_LOCAL_MACHINE)
|
|
lphKey = L"MACHINE";
|
|
else if (hKey == HKEY_USERS)
|
|
lphKey = L"USERS";
|
|
else if (hKey == HKEY_CURRENT_CONFIG)
|
|
lphKey = L"CONFIG";
|
|
else
|
|
goto Cleanup;
|
|
|
|
lpKeyPath = HeapAlloc(GetProcessHeap(),
|
|
0,
|
|
(2 + lnMachine + 1 + wcslen(lphKey) + 1 + lnKeyName) * sizeof(WCHAR));
|
|
if (lpKeyPath == NULL)
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
goto Cleanup;
|
|
}
|
|
lpKeyPath[0] = L'\0';
|
|
|
|
if (lnMachine != 0)
|
|
{
|
|
wcscat(lpKeyPath,
|
|
L"\\\\");
|
|
wcscat(lpKeyPath,
|
|
lpMachine);
|
|
wcscat(lpKeyPath,
|
|
L"\\");
|
|
}
|
|
|
|
wcscat(lpKeyPath,
|
|
lphKey);
|
|
if (lpKeyName != NULL && lpKeyName[0] != L'\0')
|
|
{
|
|
if (lpKeyName[0] != L'\\')
|
|
{
|
|
wcscat(lpKeyPath,
|
|
L"\\");
|
|
}
|
|
|
|
wcscat(lpKeyPath,
|
|
lpKeyName);
|
|
}
|
|
|
|
ObjectInfo.dwFlags = SI_EDIT_ALL | SI_ADVANCED | SI_CONTAINER | SI_EDIT_EFFECTIVE | SI_EDIT_PERMS |
|
|
SI_OWNER_RECURSE | SI_RESET_DACL_TREE | SI_RESET_SACL_TREE;
|
|
ObjectInfo.hInstance = hInst;
|
|
ObjectInfo.pszServerName = (LPWSTR)lpMachine;
|
|
ObjectInfo.pszObjectName = (LPWSTR)lpKeyName; /* FIXME */
|
|
ObjectInfo.pszPageTitle = (LPWSTR)lpKeyName; /* FIXME */
|
|
|
|
if (!(RegKeySecurity = CRegKeySecurity_fnConstructor(lpKeyPath,
|
|
hKey,
|
|
&ObjectInfo,
|
|
&Result)))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
/* display the security editor dialog */
|
|
pfnEditSecurity(hWndOwner,
|
|
impl_to_interface(RegKeySecurity,
|
|
ISecurityInformation));
|
|
|
|
/* dereference the interface, it should be destroyed here */
|
|
CRegKeySecurity_fnRelease(RegKeySecurity);
|
|
|
|
Cleanup:
|
|
if (lpKeyPath != NULL)
|
|
{
|
|
HeapFree(GetProcessHeap(),
|
|
0,
|
|
lpKeyPath);
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
/* EOF */
|