|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: printsi.cpp
//
// This file contains the implementation of the CPrintSecurity object.
//
//--------------------------------------------------------------------------
#include "rshx32.h"
// The following array defines the permission names for NT printers.
SI_ACCESS siPrintAccesses[] = { { &GUID_NULL, PRINTER_EXECUTE, MAKEINTRESOURCE(IDS_PRINT_PRINT), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC }, { &GUID_NULL, PRINTER_ALL_ACCESS, MAKEINTRESOURCE(IDS_PRINT_ADMINISTER), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC }, { &GUID_NULL, JOB_ALL_ACCESS, MAKEINTRESOURCE(IDS_PRINT_ADMINISTER_JOBS), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC | OBJECT_INHERIT_ACE | INHERIT_ONLY_ACE }, // { &GUID_NULL, DELETE, MAKEINTRESOURCE(IDS_PRINT_DELETE), SI_ACCESS_SPECIFIC },
{ &GUID_NULL, STANDARD_RIGHTS_READ, MAKEINTRESOURCE(IDS_PRINT_READ), SI_ACCESS_SPECIFIC }, { &GUID_NULL, WRITE_DAC, MAKEINTRESOURCE(IDS_PRINT_CHANGE_PERM), SI_ACCESS_SPECIFIC }, { &GUID_NULL, WRITE_OWNER, MAKEINTRESOURCE(IDS_PRINT_CHANGE_OWNER), SI_ACCESS_SPECIFIC }, { &GUID_NULL, PRINTER_ALL_ACCESS|JOB_ALL_ACCESS, MAKEINTRESOURCE(IDS_PRINT_JOB_ALL), 0 }, { &GUID_NULL, 0, MAKEINTRESOURCE(IDS_NONE), 0 }, }; #define iPrintDefAccess 0 // PRINTER_EXECUTE (i.e. "Print" access)
#define PRINTER_ALL_AUDIT (PRINTER_ALL_ACCESS | ACCESS_SYSTEM_SECURITY)
#define JOB_ALL_AUDIT (JOB_ALL_ACCESS | ACCESS_SYSTEM_SECURITY)
#define PRINTER_JOB_ALL_AUDIT (PRINTER_ALL_ACCESS | JOB_ALL_ACCESS | ACCESS_SYSTEM_SECURITY)
// The following array defines the auditting names for NT printers.
SI_ACCESS siPrintAudits[] = { { &GUID_NULL, PRINTER_EXECUTE, MAKEINTRESOURCE(IDS_PRINT_PRINT), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC }, { &GUID_NULL, PRINTER_ALL_AUDIT, MAKEINTRESOURCE(IDS_PRINT_ADMINISTER), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC }, { &GUID_NULL, JOB_ALL_AUDIT, MAKEINTRESOURCE(IDS_PRINT_ADMINISTER_JOBS), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC | OBJECT_INHERIT_ACE | INHERIT_ONLY_ACE }, // { &GUID_NULL, DELETE, MAKEINTRESOURCE(IDS_PRINT_DELETE), SI_ACCESS_SPECIFIC },
{ &GUID_NULL, STANDARD_RIGHTS_READ, MAKEINTRESOURCE(IDS_PRINT_READ), SI_ACCESS_SPECIFIC }, { &GUID_NULL, WRITE_DAC, MAKEINTRESOURCE(IDS_PRINT_CHANGE_PERM), SI_ACCESS_SPECIFIC }, { &GUID_NULL, WRITE_OWNER, MAKEINTRESOURCE(IDS_PRINT_CHANGE_OWNER), SI_ACCESS_SPECIFIC }, { &GUID_NULL, PRINTER_ALL_AUDIT|JOB_ALL_AUDIT, MAKEINTRESOURCE(IDS_PRINT_JOB_ALL), 0 }, { &GUID_NULL, 0, MAKEINTRESOURCE(IDS_NONE), 0 }, }; #define iPrintDefAudit 0 // PRINTER_EXECUTE (i.e. "Print" access)
// The following array defines the inheritance types for NT printers.
SI_INHERIT_TYPE siPrintInheritTypes[] = { &GUID_NULL, 0, MAKEINTRESOURCE(IDS_PRINT_PRINTER), &GUID_NULL, INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE, MAKEINTRESOURCE(IDS_PRINT_DOCUMENT_ONLY), &GUID_NULL, OBJECT_INHERIT_ACE, MAKEINTRESOURCE(IDS_PRINT_PRINTER_DOCUMENT), };
BOOL GetPrinterAlloc(HANDLE hPrinter, DWORD dwLevel, LPBYTE *ppBuffer) { BOOL bResult; DWORD dwLength = 0; LPBYTE pBuffer = NULL;
bResult = GetPrinter(hPrinter, dwLevel, NULL, 0, &dwLength); if (dwLength) { bResult = FALSE; pBuffer = (LPBYTE)LocalAlloc(LPTR, dwLength); if (pBuffer) { bResult = GetPrinter(hPrinter, dwLevel, pBuffer, dwLength, &dwLength); if (!bResult) { LocalFree(pBuffer); pBuffer = NULL; } } } *ppBuffer = pBuffer; return bResult; }
STDMETHODIMP CheckPrinterAccess(LPCTSTR pszObjectName, LPDWORD pdwAccessGranted, LPTSTR pszServer, ULONG cchServer) { HRESULT hr = S_OK; UINT i; PRINTER_DEFAULTS PrinterDefaults; DWORD dwAccessDesired[] = { ALL_SECURITY_ACCESS, READ_CONTROL, WRITE_DAC, WRITE_OWNER, ACCESS_SYSTEM_SECURITY }; HANDLE hPrinter = NULL;
PrinterDefaults.pDatatype = NULL; PrinterDefaults.pDevMode = NULL;
TraceEnter(TRACE_PRINTSI, "CheckPrinterAccess"); TraceAssert(pdwAccessGranted != NULL);
__try { *pdwAccessGranted = 0;
for (i = 0; i < ARRAYSIZE(dwAccessDesired); i++) { if ((dwAccessDesired[i] & *pdwAccessGranted) == dwAccessDesired[i]) continue; // already have this access
PrinterDefaults.DesiredAccess = dwAccessDesired[i];
if (OpenPrinter((LPTSTR)pszObjectName, &hPrinter, &PrinterDefaults)) { *pdwAccessGranted |= dwAccessDesired[i]; ClosePrinter(hPrinter); } else { DWORD dwErr = GetLastError();
if (dwErr != ERROR_ACCESS_DENIED && dwErr != ERROR_PRIVILEGE_NOT_HELD) { ExitGracefully(hr, HRESULT_FROM_WIN32(dwErr), "OpenPrinter failed"); } } }
if (pszServer) { PrinterDefaults.DesiredAccess = PRINTER_READ; if (OpenPrinter((LPTSTR)pszObjectName, &hPrinter, &PrinterDefaults)) { PPRINTER_INFO_2 ppi = NULL; if (GetPrinterAlloc(hPrinter, 2, (LPBYTE*)&ppi)) { if (ppi && ppi->pServerName) lstrcpyn(pszServer, ppi->pServerName, cchServer); else *pszServer = TEXT('\0'); LocalFree(ppi); } ClosePrinter(hPrinter); } } } __except(EXCEPTION_EXECUTE_HANDLER) { hr = HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND); }
exit_gracefully:
Trace((TEXT("Access = 0x%08x"), *pdwAccessGranted)); TraceLeaveResult(hr); }
STDMETHODIMP CPrintSecurity::Initialize(HDPA hItemList, DWORD dwFlags, LPTSTR pszServer, LPTSTR pszObject) { return CSecurityInformation::Initialize(hItemList, dwFlags | SI_NO_TREE_APPLY | SI_NO_ACL_PROTECT, pszServer, pszObject); }
//
// NT6 REVIEW
//
// GetAceSid, FindManagePrinterACE, MungeAclForPrinter and
// CPrintSecurity::SetSecurity only exist here because
// 1) The spooler removes JOB_ACCESS_ADMINISTER from an ACE unless the
// ACE has INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE.
// 2) The NT4 ACL editor (ACLEDIT) needs extra bogus ACEs to recognize
// "Manage Documents" access. (Must support downlevel clients.)
//
// The first case should be rare, since you have to perform certain
// steps in the NT5 ACL editor (ACLUI) to cause this situation. The
// second situation is common, since CREATER_OWNER and Administrators
// usually have "Manage Documents" access.
//
// If the spooler guys decide to not support NT4 clients for NT6, and they
// stop stripping JOB_ACCESS_ADMINISTER from ACEs, then MungeAclForPrinter
// and CPrintSecurity::SetSecurity can be removed entirely. ENCOURAGE THEM
// TO MAKE THAT CHANGE. (They can also remove similar hacks from their own
// code that add bogus ACEs for the old ACL editor.)
//
PSID GetAceSid(PACE_HEADER pAce) { switch (pAce->AceType) { case ACCESS_ALLOWED_ACE_TYPE: case ACCESS_DENIED_ACE_TYPE: case SYSTEM_AUDIT_ACE_TYPE: case SYSTEM_ALARM_ACE_TYPE: return (PSID)&((PKNOWN_ACE)pAce)->SidStart;
case ACCESS_ALLOWED_COMPOUND_ACE_TYPE: return (PSID)&((PCOMPOUND_ACCESS_ALLOWED_ACE)pAce)->SidStart;
case ACCESS_ALLOWED_OBJECT_ACE_TYPE: case ACCESS_DENIED_OBJECT_ACE_TYPE: case SYSTEM_AUDIT_OBJECT_ACE_TYPE: case SYSTEM_ALARM_OBJECT_ACE_TYPE: return RtlObjectAceSid(pAce); }
return NULL; }
PACE_HEADER FindManagePrinterACE(PACL pAcl, PSID pSid) { UINT i; PACE_HEADER pAce;
if (!pAcl || !pSid) return NULL;
for (i = 0, pAce = (PACE_HEADER)FirstAce(pAcl); i < pAcl->AceCount; i++, pAce = (PACE_HEADER)NextAce(pAce)) { if (pAce->AceType == ACCESS_ALLOWED_ACE_TYPE && (((PKNOWN_ACE)pAce)->Mask & PRINTER_ALL_ACCESS) == PRINTER_ALL_ACCESS && !(pAce->AceFlags & INHERIT_ONLY_ACE) && EqualSid(pSid, GetAceSid(pAce))) { return pAce; } }
return NULL; }
BOOL MungeAclForPrinter(PACL pAcl, PACL *ppAclOut) { USHORT i; PACE_HEADER pAce; PACE_HEADER pAceCopy = NULL;
if (ppAclOut == NULL) return FALSE;
*ppAclOut = NULL;
if (pAcl == NULL) return TRUE;
TraceEnter(TRACE_PRINTSI, "MungeAclForPrinter");
for (i = 0, pAce = (PACE_HEADER)FirstAce(pAcl); i < pAcl->AceCount; i++, pAce = (PACE_HEADER)NextAce(pAce)) { //
// If this ACE has the JOB_ACCESS_ADMINISTER bit and the inherit
// flags indicate that it applies to both printers and documents,
// then we need to treat it specially, since the spooler won't save
// JOB_ACCESS_ADMINISTER on a printer ACE (INHERIT_ONLY_ACE not set).
//
if ((((PKNOWN_ACE)pAce)->Mask & JOB_ACCESS_ADMINISTER) && (pAce->AceFlags & (INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE)) == OBJECT_INHERIT_ACE) { //
// Split into 2 aces: one with no inheritance, and one with
// INHERIT_ONLY_ACE turned on. Let the spooler do whatever
// it wants with the mask.
//
// This requires allocating a larger ACL and copying all
// previous aces over.
//
TraceMsg("Splitting JOB_ACCESS_ADMINISTER ACE into 2");
if (*ppAclOut == NULL) { //
// Allocate new ACL and copy previous aces. The length is enough
// for 1 copy of all previous aces, and 3 copies (max) of all
// remaining aces.
//
ULONG nPrevLength = (ULONG)((ULONG_PTR)pAce - (ULONG_PTR)pAcl); *ppAclOut = (PACL)LocalAlloc(LPTR, nPrevLength + (pAcl->AclSize - nPrevLength) * 3); if (!*ppAclOut) TraceLeaveValue(FALSE);
CopyMemory(*ppAclOut, pAcl, nPrevLength); (*ppAclOut)->AclSize = (USHORT)LocalSize(*ppAclOut); (*ppAclOut)->AceCount = i; pAceCopy = (PACE_HEADER)ByteOffset(*ppAclOut, nPrevLength); }
// Turn off inheritance and copy this ace
pAce->AceFlags &= ~OBJECT_INHERIT_ACE; CopyMemory(pAceCopy, pAce, pAce->AceSize); pAceCopy = (PACE_HEADER)NextAce(pAceCopy); (*ppAclOut)->AceCount++;
// Now turn on inheritance (with INHERIT_ONLY_ACE) and copy it
// again (it gets copied way down below). Note that this may
// causes the next IF clause to add a bogus ACE also.
pAce->AceFlags |= OBJECT_INHERIT_ACE | INHERIT_ONLY_ACE; }
//
// If this ACE has JOB_ALL_ACCESS and INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE,
// and there isn't also a "Manage Printers" ACE for the same SID, add a
// bogus ACE with READ_CONTROL and CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE.
// The old ACL editor on downlevel clients needs this to recognize
// "Manage Documents" access.
//
if (pAce->AceType == ACCESS_ALLOWED_ACE_TYPE && (((PKNOWN_ACE)pAce)->Mask & JOB_ALL_ACCESS) == JOB_ALL_ACCESS && (pAce->AceFlags & (INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE)) == (INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE) && !FindManagePrinterACE(pAcl, GetAceSid(pAce))) { TraceMsg("Adding bogus ACE for downlevel support");
if (*ppAclOut == NULL) { //
// Allocate new ACL and copy previous aces. The length is enough
// for 1 copy of all previous aces, and 3 copies (max) of all
// remaining aces.
//
ULONG nPrevLength = (ULONG)((ULONG_PTR)pAce - (ULONG_PTR)pAcl); *ppAclOut = (PACL)LocalAlloc(LPTR, nPrevLength + (pAcl->AclSize - nPrevLength) * 3); if (!*ppAclOut) TraceLeaveValue(FALSE);
CopyMemory(*ppAclOut, pAcl, nPrevLength); (*ppAclOut)->AclSize = (USHORT)LocalSize(*ppAclOut); (*ppAclOut)->AceCount = i; pAceCopy = (PACE_HEADER)ByteOffset(*ppAclOut, nPrevLength); }
// Copy this ace, turn on CONTAINER_INHERIT_ACE, and set
// the mask to STANDARD_RIGHTS_READ.
CopyMemory(pAceCopy, pAce, pAce->AceSize); pAceCopy->AceFlags &= ~OBJECT_INHERIT_ACE; pAceCopy->AceFlags |= INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE; ((PKNOWN_ACE)pAceCopy)->Mask = STANDARD_RIGHTS_READ; pAceCopy = (PACE_HEADER)NextAce(pAceCopy); (*ppAclOut)->AceCount++; }
if (*ppAclOut != NULL) { // Copy current ace
CopyMemory(pAceCopy, pAce, pAce->AceSize); pAceCopy = (PACE_HEADER)NextAce(pAceCopy); (*ppAclOut)->AceCount++; } }
if (*ppAclOut != NULL) { TraceAssert((ULONG_PTR)pAceCopy > (ULONG_PTR)*ppAclOut && (ULONG_PTR)pAceCopy <= (ULONG_PTR)*ppAclOut + (*ppAclOut)->AclSize);
// Set the ACL size to the correct value
(*ppAclOut)->AclSize = (WORD)((ULONG_PTR)pAceCopy - (ULONG_PTR)*ppAclOut); }
TraceLeaveValue(TRUE); }
///////////////////////////////////////////////////////////
//
// ISecurityInformation methods
//
///////////////////////////////////////////////////////////
STDMETHODIMP CPrintSecurity::SetSecurity(SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR pSD) { PACL pDacl = NULL; PACL pSacl = NULL; PACL pDaclCopy = NULL; PACL pSaclCopy = NULL; BOOL bPresent; BOOL bDefaulted; SECURITY_DESCRIPTOR sd;
TraceEnter(TRACE_PRINTSI, "CPrintSecurity::SetSecurity");
HRESULT hr = S_OK;
if ((si & DACL_SECURITY_INFORMATION) && GetSecurityDescriptorDacl(pSD, &bPresent, &pDacl, &bDefaulted) && bPresent) { if (MungeAclForPrinter(pDacl, &pDaclCopy) && pDaclCopy) pDacl = pDaclCopy; }
if ((si & SACL_SECURITY_INFORMATION) && GetSecurityDescriptorSacl(pSD, &bPresent, &pSacl, &bDefaulted) && bPresent) { if (MungeAclForPrinter(pSacl, &pSaclCopy) && pSaclCopy) pSacl = pSaclCopy; }
if (pDaclCopy || pSaclCopy) { // Build a new SECURITY_DESCRIPTOR
PSID psid; DWORD dwRevision; SECURITY_DESCRIPTOR_CONTROL sdControl = 0;
if(!GetSecurityDescriptorControl(pSD, &sdControl, &dwRevision)) { DWORD dwErr = GetLastError(); ExitGracefully(hr, HRESULT_FROM_WIN32(dwErr),"GetSecurityDescriptorControl failed"); }
if(!InitializeSecurityDescriptor(&sd, dwRevision)) { DWORD dwErr = GetLastError(); ExitGracefully(hr, HRESULT_FROM_WIN32(dwErr),"InitializeSecurityDescriptor failed"); }
sd.Control = (SECURITY_DESCRIPTOR_CONTROL)(sdControl & ~SE_SELF_RELATIVE);
if ((si & OWNER_SECURITY_INFORMATION) && GetSecurityDescriptorOwner(pSD, &psid, &bDefaulted)) { if(!SetSecurityDescriptorOwner(&sd, psid, bDefaulted)) { DWORD dwErr = GetLastError(); ExitGracefully(hr, HRESULT_FROM_WIN32(dwErr),"SetSecurityDescriptorOwner failed"); }
}
if ((si & GROUP_SECURITY_INFORMATION) && GetSecurityDescriptorGroup(pSD, &psid, &bDefaulted)) { if(!SetSecurityDescriptorGroup(&sd, psid, bDefaulted)) { DWORD dwErr = GetLastError(); ExitGracefully(hr, HRESULT_FROM_WIN32(dwErr),"SetSecurityDescriptorGroup failed"); }
}
if (si & SACL_SECURITY_INFORMATION) { if(!SetSecurityDescriptorSacl(&sd, sdControl & SE_SACL_PRESENT, pSacl, sdControl & SE_SACL_DEFAULTED)) { DWORD dwErr = GetLastError(); ExitGracefully(hr, HRESULT_FROM_WIN32(dwErr),"SetSecurityDescriptorSacl failed"); }
}
if (si & DACL_SECURITY_INFORMATION) { if(!SetSecurityDescriptorDacl(&sd, sdControl & SE_DACL_PRESENT, pDacl, sdControl & SE_DACL_DEFAULTED)) { DWORD dwErr = GetLastError(); ExitGracefully(hr, HRESULT_FROM_WIN32(dwErr),"SetSecurityDescriptorDacl failed"); }
}
// Switch to the new security descriptor
pSD = &sd; }
// The base class does the rest of the work
hr = CSecurityInformation::SetSecurity(si, pSD);
exit_gracefully:
if (pDaclCopy) LocalFree(pDaclCopy);
if (pSaclCopy) LocalFree(pSaclCopy);
TraceLeaveResult(hr); }
STDMETHODIMP CPrintSecurity::GetAccessRights(const GUID* /*pguidObjectType*/, DWORD dwFlags, PSI_ACCESS *ppAccesses, ULONG *pcAccesses, ULONG *piDefaultAccess) { TraceEnter(TRACE_PRINTSI, "CPrintSecurity::GetAccessRights"); TraceAssert(ppAccesses != NULL); TraceAssert(pcAccesses != NULL); TraceAssert(piDefaultAccess != NULL);
if (dwFlags & SI_EDIT_AUDITS) { *ppAccesses = siPrintAudits; *pcAccesses = ARRAYSIZE(siPrintAudits); *piDefaultAccess = iPrintDefAudit; } else { *ppAccesses = siPrintAccesses; *pcAccesses = ARRAYSIZE(siPrintAccesses); *piDefaultAccess = iPrintDefAccess; }
TraceLeaveResult(S_OK); }
GENERIC_MAPPING JobMap = { JOB_READ, JOB_WRITE, JOB_EXECUTE, JOB_ALL_ACCESS };
GENERIC_MAPPING PrinterMap = { PRINTER_READ, PRINTER_WRITE, PRINTER_EXECUTE, PRINTER_ALL_ACCESS };
GENERIC_MAPPING FullPrinterMap = { PRINTER_READ | JOB_READ, PRINTER_WRITE | JOB_WRITE, PRINTER_EXECUTE | JOB_EXECUTE, PRINTER_ALL_ACCESS | JOB_ALL_ACCESS };
STDMETHODIMP CPrintSecurity::MapGeneric(const GUID* /*pguidObjectType*/, UCHAR *pAceFlags, ACCESS_MASK *pmask) { PGENERIC_MAPPING pMap;
TraceEnter(TRACE_PRINTSI, "CPrintSecurity::MapGeneric"); TraceAssert(pAceFlags != NULL); TraceAssert(pmask != NULL);
// This flag has no meaning for printers, but it's often turned on
// in legacy ACLs. Turn it off here
*pAceFlags &= ~CONTAINER_INHERIT_ACE;
// Choose the correct generic mapping according to the inherit
// scope of this ACE.
if (*pAceFlags & OBJECT_INHERIT_ACE) { if (*pAceFlags & INHERIT_ONLY_ACE) pMap = &JobMap; // documents only
else pMap = &FullPrinterMap; // printers & documents
} else pMap = &PrinterMap; // printers only
// Note that the case where INHERIT_ONLY_ACE is ON but OBJECT_INHERIT_ACE
// is OFF falls under the "printers only" case above. However, this
// case makes no sense (inherit-only, but not onto documents) and it
// doesn't matter how we do the mapping.
// Map any generic bits to standard & specific bits.
// When using the NT5 ACL APIs, ntmarta.dll maps generic bits, so this
// isn't always necessary, but we'll do it anyway to be sure.
MapGenericMask(pmask, pMap);
// Turn off any extra bits that ntmarta.dll may have turned on
// (ntmarta uses a different mapping). But leave ACCESS_SYSTEM_SECURITY
// alone in case we're editing a SACL.
*pmask &= (pMap->GenericAll | ACCESS_SYSTEM_SECURITY);
TraceLeaveResult(S_OK); }
STDMETHODIMP CPrintSecurity::GetInheritTypes(PSI_INHERIT_TYPE *ppInheritTypes, ULONG *pcInheritTypes) { TraceEnter(TRACE_PRINTSI, "CPrintSecurity::GetInheritTypes"); TraceAssert(ppInheritTypes != NULL); TraceAssert(pcInheritTypes != NULL);
*ppInheritTypes = siPrintInheritTypes; *pcInheritTypes = ARRAYSIZE(siPrintInheritTypes);
TraceLeaveResult(S_OK); }
//
// The base class versions of ReadObjectSecurity and WriteObjectSecurity
// use Get/SetNamedSecurityInfo, et al. These API's are generic,
// involve lots of conversions, and are problematic. Since there is no
// inheritance propagation required for printers, override them here
// and use GetPrinter/SetPrinter.
//
STDMETHODIMP CPrintSecurity::ReadObjectSecurity(LPCTSTR pszObject, SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR *ppSD) { HRESULT hr; DWORD dwErr = NOERROR; HANDLE hPrinter; PRINTER_DEFAULTS pd = {0}; DWORD dwLength = 0;
TraceEnter(TRACE_PRINTSI, "CPrintSecurity::ReadObjectSecurity"); TraceAssert(pszObject != NULL); TraceAssert(si != 0); TraceAssert(ppSD != NULL);
//
// Assume that required privileges have already been
// enabled, if appropriate.
//
if (si & (DACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION)) pd.DesiredAccess |= READ_CONTROL;
if (si & SACL_SECURITY_INFORMATION) pd.DesiredAccess |= ACCESS_SYSTEM_SECURITY;
__try { *ppSD = NULL;
if (OpenPrinter((LPTSTR)pszObject, &hPrinter, &pd)) { PPRINTER_INFO_3 ppi = NULL;
if (GetPrinterAlloc(hPrinter, 3, (LPBYTE*)&ppi)) { //
// Rather than allocating a new buffer and copying the
// security descriptor, we can re-use the existing buffer
// by simply moving the security descriptor to the top.
//
dwLength = GetSecurityDescriptorLength(ppi->pSecurityDescriptor); *ppSD = ppi; // This is an overlapped copy, so use MoveMemory.
MoveMemory(*ppSD, ppi->pSecurityDescriptor, dwLength); } else dwErr = GetLastError();
ClosePrinter(hPrinter); } else dwErr = GetLastError(); } __except(EXCEPTION_EXECUTE_HANDLER) { dwErr = ERROR_PROC_NOT_FOUND; }
hr = HRESULT_FROM_WIN32(dwErr); TraceLeaveResult(hr); }
STDMETHODIMP CPrintSecurity::WriteObjectSecurity(LPCTSTR pszObject, SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR pSD) { HRESULT hr; DWORD dwErr = NOERROR; HANDLE hPrinter; PRINTER_DEFAULTS pd = {0};
TraceEnter(TRACE_PRINTSI, "CPrintSecurity::WriteObjectSecurity"); TraceAssert(pszObject != NULL); TraceAssert(si != 0); TraceAssert(pSD != NULL);
//
// Assume that required privileges have already been
// enabled, if appropriate.
//
if (si & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION)) pd.DesiredAccess |= WRITE_OWNER;
if (si & SACL_SECURITY_INFORMATION) pd.DesiredAccess |= ACCESS_SYSTEM_SECURITY;
if (si & DACL_SECURITY_INFORMATION) pd.DesiredAccess |= WRITE_DAC;
__try { if (OpenPrinter((LPTSTR)pszObject, &hPrinter, &pd)) { PRINTER_INFO_3 pi = { pSD };
if (!SetPrinter(hPrinter, 3, (LPBYTE)&pi, 0)) dwErr = GetLastError();
ClosePrinter(hPrinter); } else dwErr = GetLastError(); } __except(EXCEPTION_EXECUTE_HANDLER) { dwErr = ERROR_PROC_NOT_FOUND; }
hr = HRESULT_FROM_WIN32(dwErr); TraceLeaveResult(hr); }
STDMETHODIMP CPrintSecurity::GetInheritSource(SECURITY_INFORMATION si, PACL pACL, PINHERITED_FROM *ppInheritArray) { return E_NOTIMPL; }
|