|
|
//
// ISecurityInformation interface implementation
//
#include <aclui.h>
#include "faxui.h"
class CFaxSecurity : public ISecurityInformation { protected: ULONG m_cRef;
STDMETHOD(MakeSelfRelativeCopy)(PSECURITY_DESCRIPTOR psdOriginal, PSECURITY_DESCRIPTOR* ppsdNew); public: CFaxSecurity() : m_cRef(1) {} virtual ~CFaxSecurity() {}
// IUnknown methods
STDMETHOD(QueryInterface)(REFIID, LPVOID *); STDMETHOD_(ULONG, AddRef)(); STDMETHOD_(ULONG, Release)();
// ISecurityInformation methods
STDMETHOD(GetObjectInformation)(PSI_OBJECT_INFO pObjectInfo);
STDMETHOD(GetSecurity)(SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR *ppSD, BOOL fDefault);
STDMETHOD(SetSecurity)(SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR pSD);
STDMETHOD(GetAccessRights)(const GUID* pguidObjectType, DWORD dwFlags, PSI_ACCESS *ppAccess, ULONG *pcAccesses, ULONG *piDefaultAccess);
STDMETHOD(MapGeneric)(const GUID *pguidObjectType, UCHAR *pAceFlags, ACCESS_MASK *pmask);
STDMETHOD(GetInheritTypes)(PSI_INHERIT_TYPE *ppInheritTypes, ULONG *pcInheritTypes);
STDMETHOD(PropertySheetPageCallback)(HWND hwnd, UINT uMsg, SI_PAGE_TYPE uPage); };
CFaxSecurity* g_pFaxSecurity = NULL;
///////////////////////////////////////////////////////////
//
// IUnknown methods
//
///////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CFaxSecurity::AddRef() { return ++m_cRef; }
STDMETHODIMP_(ULONG) CFaxSecurity::Release() { if (--m_cRef == 0) { delete this; g_pFaxSecurity = NULL; return 0; }
return m_cRef; }
STDMETHODIMP CFaxSecurity::QueryInterface(REFIID riid, LPVOID FAR* ppv) { if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ISecurityInformation)) { *ppv = (LPSECURITYINFO)this; m_cRef++; return S_OK; } else { *ppv = NULL; return E_NOINTERFACE; } }
///////////////////////////////////////////////////////////
//
// ISecurityInformation methods
//
///////////////////////////////////////////////////////////
STDMETHODIMP CFaxSecurity::GetObjectInformation(PSI_OBJECT_INFO pObjectInfo) // *** ISecurityInformation methods implementation ***
/*
- CFaxSecurity::GetObjectInformation - * Purpose: * Performs an access check against the fax service security descriptor * * Arguments: * [in] pObjectInfo - pointer to object information structure. * * Return: * OLE error code */ { DWORD ec = ERROR_SUCCESS; if(!Connect(NULL, FALSE)) { return S_FALSE; }
HANDLE hPrivBeforeSE_TAKE_OWNERSHIP = INVALID_HANDLE_VALUE; HANDLE hPrivBeforeSE_SECURITY = INVALID_HANDLE_VALUE;
if( pObjectInfo == NULL ) { Error(("Invalid parameter - pObjectInfo == NULL\n")); Assert( pObjectInfo != NULL ); return E_POINTER; }
//
// Set Flags
//
pObjectInfo->dwFlags = SI_EDIT_ALL | SI_NO_TREE_APPLY | SI_NO_ACL_PROTECT | SI_ADVANCED | SI_PAGE_TITLE; //
// Check if to add SI_READONLY
//
if (!FaxAccessCheckEx(g_hFaxSvcHandle, WRITE_DAC, NULL)) { ec = GetLastError(); if (ERROR_SUCCESS == ec) { pObjectInfo->dwFlags |= SI_READONLY; } else { Error(("FaxAccessCheckEx(WRITE_DAC) failed with %d \n", ec)); goto exit; } }
//
// Check if to add SI_OWNER_READONLY
//
hPrivBeforeSE_TAKE_OWNERSHIP = EnablePrivilege (SE_TAKE_OWNERSHIP_NAME); //
// No error checking - If we failed we will get ERROR_ACCESS_DENIED in the access check
//
if (!FaxAccessCheckEx(g_hFaxSvcHandle,WRITE_OWNER, NULL)) { ec = GetLastError(); if (ERROR_SUCCESS == ec) { pObjectInfo->dwFlags |= SI_OWNER_READONLY; } else { Error(("FaxAccessCheckEx(WRITE_OWNER) failed with %d \n", ec)); goto exit; } }
//
// Check if to remove SI_EDIT_AUDITS
//
hPrivBeforeSE_SECURITY = EnablePrivilege (SE_SECURITY_NAME); //
// No error checking - If we failed we will get ERROR_ACCESS_DENIED in the access check
//
if (!FaxAccessCheckEx(g_hFaxSvcHandle, ACCESS_SYSTEM_SECURITY, NULL)) { ec = GetLastError(); if (ERROR_SUCCESS == ec) { pObjectInfo->dwFlags &= ~SI_EDIT_AUDITS; } else { Error(("FaxAccessCheckEx(ACCESS_SYSTEM_SECURITY) failed with %d \n", ec)); goto exit; } }
//
// Set all other fields
//
static TCHAR tszPageTitle[MAX_PATH] = {0}; if(LoadString((HINSTANCE)g_hResource, IDS_SECURITY_TITLE, tszPageTitle, ARR_SIZE(tszPageTitle))) { pObjectInfo->pszPageTitle = tszPageTitle; } else { ec = GetLastError(); Error(("LoadString(IDS_SECURITY_TITLE) failed with %d \n", ec));
pObjectInfo->pszPageTitle = NULL; }
static TCHAR tszPrinterName[MAX_PATH] = {0}; if(GetFirstLocalFaxPrinterName(tszPrinterName, ARR_SIZE(tszPrinterName))) { pObjectInfo->pszObjectName = tszPrinterName; } else { ec = GetLastError(); Error(("GetFirstLocalFaxPrinterName() failed with %d \n", ec));
pObjectInfo->pszObjectName = NULL; } pObjectInfo->hInstance = (HINSTANCE)g_hResource; pObjectInfo->pszServerName = NULL;
exit: ReleasePrivilege (hPrivBeforeSE_SECURITY); ReleasePrivilege (hPrivBeforeSE_TAKE_OWNERSHIP); return HRESULT_FROM_WIN32(ec);
} // CFaxSecurity::GetObjectInformation
STDMETHODIMP CFaxSecurity::GetSecurity(SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR* ppSD, BOOL fDefault) /*
- CFaxSecurityInformation::GetSecurity - * Purpose: * requests a security descriptor for the securable object whose * security descriptor is being edited. The access control editor * calls this method to retrieve the object's current or default security descriptor. * * Arguments: * [in] RequestedInformation - security information. * [out] ppSecurityDescriptor - pointer to security descriptor. * [in] fDefault - not implemented * * Return: * OLE error code */ { HRESULT hRc = S_OK; DWORD ec = ERROR_SUCCESS;
PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
HANDLE hPrivBeforeSE_SECURITY = INVALID_HANDLE_VALUE;
Assert(ppSD);
if(!Connect(NULL, FALSE)) { return S_FALSE; } if( fDefault == TRUE ) { Error(("Non implemeted feature -> fDefault == TRUE\n")); return E_NOTIMPL; }
if (si & SACL_SECURITY_INFORMATION) { hPrivBeforeSE_SECURITY = EnablePrivilege (SE_SECURITY_NAME); }
//
// Get the current relative descriptor from the fax server
//
if(!FaxGetSecurityEx(g_hFaxSvcHandle, si, &pSecurityDescriptor)) { ec = GetLastError(); Error(("FaxGetSecurityEx() failed with %d\n", ec)); hRc = HRESULT_FROM_WIN32(ec); goto exit; }
//
// return a self relative descriptor copy allocated with LocalAlloc()
//
hRc = MakeSelfRelativeCopy( pSecurityDescriptor, ppSD ); if( FAILED( hRc ) ) { Error(("MakeSelfRelativeCopy() failed with %08X\n", hRc)); goto exit; } Assert(S_OK == hRc); exit: if (pSecurityDescriptor) { FaxFreeBuffer(pSecurityDescriptor); } ReleasePrivilege (hPrivBeforeSE_SECURITY);
return hRc;
} // CFaxSecurity::GetSecurity
STDMETHODIMP CFaxSecurity::SetSecurity(SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR pSD) /*
- CFaxSecurityInformation::SetSecurity - * Purpose: * Provides a security descriptor containing the security information * the user wants to apply to the securable object. The access control * editor calls this method when the user clicks the Okay or Apply buttons. * * Arguments: * [in] SecurityInformation - security information structure. * [in] pSecurityDescriptor - pointer to security descriptor. * * Return: * OLE error code */ { HRESULT hRc = S_OK; DWORD ec = ERROR_SUCCESS;
PSECURITY_DESCRIPTOR psdSelfRelativeCopy = NULL; HANDLE hPrivBeforeSE_TAKE_OWNERSHIP = INVALID_HANDLE_VALUE; HANDLE hPrivBeforeSE_SECURITY = INVALID_HANDLE_VALUE; Assert(pSD); Assert( IsValidSecurityDescriptor( pSD )); if(!Connect(NULL, FALSE)) { return S_FALSE; }
//
// Prepare self relative descriptor
//
hRc = MakeSelfRelativeCopy( pSD, &psdSelfRelativeCopy ); if( FAILED( hRc ) ) { Error(("MakeSelfRelativeCopy() failed with %08X\n", hRc)); goto exit; }
if (si & OWNER_SECURITY_INFORMATION) { hPrivBeforeSE_TAKE_OWNERSHIP = EnablePrivilege (SE_TAKE_OWNERSHIP_NAME); }
if (si & SACL_SECURITY_INFORMATION) { hPrivBeforeSE_SECURITY = EnablePrivilege (SE_SECURITY_NAME); } //
// save the new relative descriptor to the fax server
//
if(!FaxSetSecurity(g_hFaxSvcHandle, si, psdSelfRelativeCopy)) { ec = GetLastError(); Error(("FaxSetSecurity() failed with %d\n", ec)); hRc = HRESULT_FROM_WIN32(ec); goto exit; }
Assert( S_OK == hRc || E_ACCESSDENIED == hRc);
exit: if (psdSelfRelativeCopy) { ::LocalFree(psdSelfRelativeCopy); }
ReleasePrivilege (hPrivBeforeSE_SECURITY); ReleasePrivilege (hPrivBeforeSE_TAKE_OWNERSHIP); return hRc;
} // CFaxSecurity::SetSecurity
STDMETHODIMP CFaxSecurity::GetAccessRights(const GUID* pguidObjectType, DWORD dwFlags, PSI_ACCESS* ppAccess, ULONG* pcAccesses, ULONG* piDefaultAccess) /*
- CFaxSecurityInformation::GetAccessRights - * Purpose: * Requests information about the access rights that can be * controlled for a securable object. The access control * editor calls this method to retrieve display strings and * other information used to initialize the property pages. * * Arguments: * [in] pguidObjectType - Pointer to a GUID structure that * identifies the type of object for which * access rights are being requested. * [in] dwFlags - A set of bit flags that indicate the property * page being initialized * [out] ppAccess - Pointer to a variable that you should * set to a pointer to an array of SI_ACCESS * structures. * [out] pcAccesses - Pointer to a variable that you should set * to indicate the number of entries in the ppAccess array. * [out] piDefaultAccess - Pointer to a variable that you should set * to indicate the zero-based index of the array entry that contains * the default access rights. * The access control editor uses this entry as the initial access rights in a new ACE. * * Return: * OLE error code */ { Assert( ppAccess ); Assert( pcAccesses ); Assert( piDefaultAccess );
//
// Access rights for the Basic security page
//
static SI_ACCESS siFaxBasicAccess[] = { // 0 Fax
{ &GUID_NULL, FAX_ACCESS_SUBMIT_HIGH | FAX_ACCESS_SUBMIT_NORMAL | FAX_ACCESS_SUBMIT | FAX_ACCESS_QUERY_IN_ARCHIVE, MAKEINTRESOURCE(IDS_RIGHT_FAX), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC }, // 1 Manage fax configuration
{ &GUID_NULL, FAX_ACCESS_MANAGE_CONFIG | FAX_ACCESS_QUERY_CONFIG, MAKEINTRESOURCE(IDS_RIGHT_MNG_CFG), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC }, // 2 Manage fax documents
{ &GUID_NULL, FAX_ACCESS_MANAGE_JOBS | FAX_ACCESS_QUERY_JOBS | FAX_ACCESS_MANAGE_IN_ARCHIVE | FAX_ACCESS_QUERY_IN_ARCHIVE | FAX_ACCESS_MANAGE_OUT_ARCHIVE | FAX_ACCESS_QUERY_OUT_ARCHIVE, MAKEINTRESOURCE(IDS_RIGHT_MNG_DOC), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC } };
//
// Access rights for the Advanced security page
//
static SI_ACCESS siFaxAccess[] = { // 0 submit permission
{ &GUID_NULL, FAX_ACCESS_SUBMIT , MAKEINTRESOURCE(IDS_FAXSEC_SUB_LOW), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC }, // 1 submit normal permission
{ &GUID_NULL, FAX_ACCESS_SUBMIT_NORMAL , MAKEINTRESOURCE(IDS_FAXSEC_SUB_NORMAL), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC }, // 2 submit high permission
{ &GUID_NULL, FAX_ACCESS_SUBMIT_HIGH , MAKEINTRESOURCE(IDS_FAXSEC_SUB_HIGH), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC }, // 3 query jobs
{ &GUID_NULL, FAX_ACCESS_QUERY_JOBS, MAKEINTRESOURCE(IDS_FAXSEC_JOB_QRY), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC }, // 4 Manage jobs
{ &GUID_NULL, FAX_ACCESS_MANAGE_JOBS, MAKEINTRESOURCE(IDS_FAXSEC_JOB_MNG), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC }, // 5 query configuration
{ &GUID_NULL, FAX_ACCESS_QUERY_CONFIG, MAKEINTRESOURCE(IDS_FAXSEC_CONFIG_QRY), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC }, // 6 Manage configuration
{ &GUID_NULL, FAX_ACCESS_MANAGE_CONFIG, MAKEINTRESOURCE(IDS_FAXSEC_CONFIG_SET), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC }, // 7 Query incoming faxes archive
{ &GUID_NULL, FAX_ACCESS_QUERY_IN_ARCHIVE, MAKEINTRESOURCE(IDS_FAXSEC_QRY_IN_ARCH), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC }, // 8 Manage incoming faxes archive
{ &GUID_NULL, FAX_ACCESS_MANAGE_IN_ARCHIVE, MAKEINTRESOURCE(IDS_FAXSEC_MNG_IN_ARCH), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC }, // 9 Query outgoing faxes archive
{ &GUID_NULL, FAX_ACCESS_QUERY_OUT_ARCHIVE, MAKEINTRESOURCE(IDS_FAXSEC_QRY_OUT_ARCH), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC }, // 10 Manage outgoing faxes archive
{ &GUID_NULL, FAX_ACCESS_MANAGE_OUT_ARCHIVE, MAKEINTRESOURCE(IDS_FAXSEC_MNG_OUT_ARCH), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC }, // specific permissions
// 11 Read permission
{ &GUID_NULL, READ_CONTROL, MAKEINTRESOURCE(IDS_FAXSEC_READ_PERM), SI_ACCESS_SPECIFIC }, // 12 Change Permissions
{ &GUID_NULL, WRITE_DAC, MAKEINTRESOURCE(IDS_FAXSEC_CHNG_PERM), SI_ACCESS_SPECIFIC }, // 13 Take ownership
{ &GUID_NULL, WRITE_OWNER, MAKEINTRESOURCE(IDS_FAXSEC_CHNG_OWNER), SI_ACCESS_SPECIFIC } };
*ppAccess = (0 == dwFlags) ? siFaxBasicAccess : siFaxAccess; *pcAccesses = ULONG((0 == dwFlags) ? ARR_SIZE(siFaxBasicAccess) : ARR_SIZE(siFaxAccess)); *piDefaultAccess = (0 == dwFlags) ? 0 : 1;
return S_OK;
} // CFaxSecurity::GetAccessRights
STDMETHODIMP CFaxSecurity::MapGeneric(const GUID* pguidObjectType, UCHAR* pAceFlags, ACCESS_MASK* pmask) /*
- CFaxSecurityInformation::MapGeneric - * Purpose: * Requests that the generic access rights in an access mask * be mapped to their corresponding standard and specific access rights. * * Arguments: * * Return: * OLE error code */ { static GENERIC_MAPPING genericMapping = { (STANDARD_RIGHTS_READ | FAX_GENERIC_READ), // GenericRead
(STANDARD_RIGHTS_WRITE | FAX_GENERIC_WRITE), // GenericWrite
(STANDARD_RIGHTS_EXECUTE | FAX_GENERIC_EXECUTE), // GenericExecute
(READ_CONTROL | WRITE_DAC | WRITE_OWNER | FAX_GENERIC_ALL) // GenericAll
};
MapGenericMask(pmask, &genericMapping);
return S_OK; }
STDMETHODIMP CFaxSecurity::GetInheritTypes(PSI_INHERIT_TYPE* ppInheritTypes, ULONG* pcInheritTypes) { return E_NOTIMPL; }
STDMETHODIMP CFaxSecurity::PropertySheetPageCallback(HWND hwnd, UINT uMsg, SI_PAGE_TYPE uPage) { return S_OK; }
HRESULT CFaxSecurity::MakeSelfRelativeCopy(PSECURITY_DESCRIPTOR psdOriginal, PSECURITY_DESCRIPTOR* ppsdNew) /*
- CFaxSecurityInformation::MakeSelfRelativeCopy - * Purpose: * This pravite method copies Security descriptors * * Arguments: * * Return: * OLE error code */ { Assert( NULL != psdOriginal );
//
// we have to find out whether the original is already self-relative
//
SECURITY_DESCRIPTOR_CONTROL sdc = 0; PSECURITY_DESCRIPTOR psdSelfRelativeCopy = NULL; DWORD dwRevision = 0; DWORD cb = 0;
Assert(IsValidSecurityDescriptor( psdOriginal ) );
if( !::GetSecurityDescriptorControl( psdOriginal, &sdc, &dwRevision ) ) { DWORD err = ::GetLastError(); Error(("GetSecurityDescriptorControl() failed with %d\n", err)); return HRESULT_FROM_WIN32( err ); }
if( sdc & SE_SELF_RELATIVE ) { // the original is in self-relative format, just byte-copy it
// get size
cb = ::GetSecurityDescriptorLength( psdOriginal );
// alloc the memory
psdSelfRelativeCopy = (PSECURITY_DESCRIPTOR) ::LocalAlloc( LMEM_ZEROINIT, cb ); if(NULL == psdSelfRelativeCopy) { Error(("Out of memory.\n")); return E_OUTOFMEMORY; }
// make the copy
::memcpy( psdSelfRelativeCopy, psdOriginal, cb ); } else { // the original is in absolute format, convert-copy it
// get new size - it will fail and set cb to the correct buffer size
::MakeSelfRelativeSD( psdOriginal, NULL, &cb );
// alloc the new amount of memory
psdSelfRelativeCopy = (PSECURITY_DESCRIPTOR) ::LocalAlloc( LMEM_ZEROINIT, cb ); if(!psdSelfRelativeCopy) { Error(("Out of memory.\n")); return E_OUTOFMEMORY; // just in case the exception is ignored
}
if( !::MakeSelfRelativeSD( psdOriginal, psdSelfRelativeCopy, &cb ) ) { DWORD err = ::GetLastError(); Error(("MakeSelfRelativeSD() failed with %d\n", err));
::LocalFree( psdSelfRelativeCopy );
return HRESULT_FROM_WIN32( err ); } }
*ppsdNew = psdSelfRelativeCopy; return S_OK; }
///////////////////////////////////////////////////////////////////////////////
//
// This is the entry point function called from our code
//
///////////////////////////////////////////////////////////////////////////////
HMODULE g_hAclui = NULL;
extern "C" HPROPSHEETPAGE CreateFaxSecurityPage() { HPROPSHEETPAGE hPage = NULL; HPROPSHEETPAGE (*pfCreateSecurityPage)(LPSECURITYINFO) = NULL; if(!IsWinXPOS()) { //
// The security page should bge added only to the local fax printer on XP OS.
//
Assert(FALSE); return NULL; }
//
// CreateSecurityPage() Requires Windows 2000 or later, so we connect to it dynamically
//
if(!g_hAclui) { g_hAclui = LoadLibrary(TEXT("aclui.dll")); if(!g_hAclui) { Error(("LoadLibrary(aclui.dll) failed with %d\n", GetLastError())); goto error; } } (FARPROC&)pfCreateSecurityPage = GetProcAddress(g_hAclui, "CreateSecurityPage"); if(!pfCreateSecurityPage) { Error(("GetProcAddress(CreateSecurityPage) failed with %d\n", GetLastError())); goto error; }
if(!g_pFaxSecurity) { g_pFaxSecurity = new CFaxSecurity(); }
if(!g_pFaxSecurity) { Error(("Out of memory.\n")); goto error; }
hPage = pfCreateSecurityPage(g_pFaxSecurity); if(!hPage) { Error(("CreateSecurityPage() failed with %d\n", ::GetLastError())); goto error; }
return hPage;
error:
if(g_hAclui) { FreeLibrary(g_hAclui); g_hAclui = NULL; }
return NULL; }
extern "C" void ReleaseFaxSecurity() { if(g_pFaxSecurity) { g_pFaxSecurity->Release(); }
if(g_hAclui) { FreeLibrary(g_hAclui); g_hAclui = NULL; } }
|