windows-nt/Source/XPSP1/NT/printscan/ui/printui/prtsec.cxx
2020-09-26 16:20:57 +08:00

1220 lines
29 KiB
C++

/*++
Copyright (C) Microsoft Corporation, 1995 - 1997
All rights reserved.
Module Name:
prtsec.cxx
Abstract:
Print queue administration.
Author:
Albert Ting (AlbertT) 28-Aug-1995
Environment:
Revision History:
28-Aug-1995 AlbertT Munged from prtq32.c.
--*/
#include "precomp.hxx"
#pragma hdrstop
#include "time.hxx"
#include "psetup.hxx"
#include "drvsetup.hxx"
#include "instarch.hxx"
#include "portslv.hxx"
#include "dsinterf.hxx"
#include "prtprop.hxx"
#ifdef SECURITY
#ifndef UNICODE
#error "Acledit entrypoints are Unicode only."
#endif
LPCTSTR gpszAclEdit = TEXT( "acledit.dll" );
LPCSTR gpszSedDiscretionaryAclEditor = "SedDiscretionaryAclEditor";
LPCSTR gpszSedSystemAclEditor = "SedSystemAclEditor";
LPCSTR gpszSedTakeOwnership = "SedTakeOwnership";
HINSTANCE TPrinterSecurity::ghLibraryAcledit;
TPrinterSecurity::PFNSED_DISCRETIONARY_ACL_EDITOR
TPrinterSecurity::gpfnSedDiscretionaryAclEditor;
TPrinterSecurity::PFNSED_SYSTEM_ACL_EDITOR
TPrinterSecurity::gpfnSedSystemAclEditor;
TPrinterSecurity::PFNSED_TAKE_OWNERSHIP
TPrinterSecurity::gpfnSedTakeOwnership;
BOOL TPrinterSecurity::gbStringsLoaded = FALSE;
GENERIC_MAPPING
TPrinterSecurity::gGenericMappingPrinters = {
PRINTER_READ,
PRINTER_WRITE,
PRINTER_EXECUTE,
PRINTER_ALL_ACCESS
};
GENERIC_MAPPING
TPrinterSecurity::gGenericMappingDocuments = {
JOB_READ,
JOB_WRITE,
JOB_EXECUTE,
JOB_ALL_ACCESS
};
SED_HELP_INFO
TPrinterSecurity::gHelpInfoPermissions = {
NULL,
{
ID_HELP_PERMISSIONS_MAIN_DLG,
0,
0,
ID_HELP_PERMISSIONS_ADD_USER_DLG,
ID_HELP_PERMISSIONS_LOCAL_GROUP,
ID_HELP_PERMISSIONS_GLOBAL_GROUP,
ID_HELP_PERMISSIONS_FIND_ACCOUNT
}
};
SED_HELP_INFO
TPrinterSecurity::gHelpInfoAuditing = {
NULL,
{
ID_HELP_AUDITING_MAIN_DLG,
0,
0,
ID_HELP_AUDITING_ADD_USER_DLG,
ID_HELP_AUDITING_LOCAL_GROUP,
ID_HELP_AUDITING_GLOBAL_GROUP,
ID_HELP_AUDITING_FIND_ACCOUNT
}
};
SED_HELP_INFO
TPrinterSecurity::gHelpInfoTakeOwnership = {
NULL,
{
ID_HELP_TAKE_OWNERSHIP
}
};
SED_OBJECT_TYPE_DESCRIPTOR
TPrinterSecurity::gObjectTypeDescriptor = {
SED_REVISION1, // Revision
TRUE, // IsContainer
TRUE, // AllowNewObjectPerms
TRUE, // MapSpecificPermsToGeneric
&TPrinterSecurity::gGenericMappingPrinters, // GenericMapping
&TPrinterSecurity::gGenericMappingDocuments, // GenericMappingNewObjects
NULL, // ObjectTypeName
NULL, // HelpInfo
NULL, // ApplyToSubContainerTitle
NULL, // ApplyToObjectsTitle
NULL, // ApplyToSubContainerConfirmation
NULL, // SpecialObjectAccessTitle
NULL // SpecialNewObjectAccessTitle
};
//
// Application accesses passed to the discretionary ACL editor
// as well as the Take Ownership dialog.
//
SED_APPLICATION_ACCESS
TPrinterSecurity::gpDiscretionaryAccessGroup[TPrinterSecurity::PERMS_COUNT] = {
//
// No Access:
//
{
SED_DESC_TYPE_CONT_AND_NEW_OBJECT, // Type
0, // AccessMask1
0, // AccessMask2
NULL // PermissionTitle
},
//
// Print permission:
//
{
SED_DESC_TYPE_CONT_AND_NEW_OBJECT,
GENERIC_EXECUTE | GENERIC_READ | GENERIC_WRITE,
ACCESS_MASK_NEW_OBJ_NOT_SPECIFIED,
NULL
},
//
// Document Administer permission:
//
{
SED_DESC_TYPE_CONT_AND_NEW_OBJECT,
STANDARD_RIGHTS_READ,
GENERIC_ALL,
NULL
},
//
// Administer permission:
//
{
SED_DESC_TYPE_CONT_AND_NEW_OBJECT,
GENERIC_ALL,
GENERIC_ALL,
NULL
}
};
//
// Application accesses passed to the system ACL editor:
//
SED_APPLICATION_ACCESS
TPrinterSecurity::gpSystemAccessGroup[TPrinterSecurity::PERMS_AUDIT_COUNT] = {
//
// Print permission:
//
{
SED_DESC_TYPE_AUDIT,
PRINTER_ACCESS_USE,
ACCESS_MASK_NEW_OBJ_NOT_SPECIFIED,
NULL
},
{
SED_DESC_TYPE_AUDIT,
PRINTER_ACCESS_ADMINISTER | ACCESS_SYSTEM_SECURITY,
ACCESS_MASK_NEW_OBJ_NOT_SPECIFIED,
NULL
},
{
SED_DESC_TYPE_AUDIT,
DELETE,
ACCESS_MASK_NEW_OBJ_NOT_SPECIFIED,
NULL
},
{
SED_DESC_TYPE_AUDIT,
WRITE_DAC,
ACCESS_MASK_NEW_OBJ_NOT_SPECIFIED,
NULL
},
{
SED_DESC_TYPE_AUDIT,
WRITE_OWNER,
ACCESS_MASK_NEW_OBJ_NOT_SPECIFIED,
NULL
}
};
/********************************************************************
Acquire a single privilege. This routine needs to be rewritten
if multiple privleges are required at once.
********************************************************************/
class TAcquirePrivilege {
SIGNATURE( 'acpr' )
public:
TAcquirePrivilege( LPTSTR pszPrivilegeName );
~TAcquirePrivilege();
BOOL
bValid(
VOID
)
{
return _pPrivilegesOld ? TRUE : FALSE;
}
private:
enum _CONSTANTS {
kPrivilegeSizeHint = 256,
kPrivCount = 1
};
HANDLE _hToken;
PTOKEN_PRIVILEGES _pPrivilegesOld;
};
/********************************************************************
TAcquirePrivilege
********************************************************************/
TAcquirePrivilege::
TAcquirePrivilege(
LPTSTR pszPrivilegeName
) : _hToken( NULL ), _pPrivilegesOld( NULL )
/*++
Routine Description:
This adjusts the token to acquire one privilege.
Note: This is efficient only for acquiring a single privilege.
For multiple privileges, this routine should be rewritten
so that the _hToken is reused.
Arguments:
pszPrivilegeName - Privilege string to acquire.
Return Value:
--*/
{
if( !OpenThreadToken( GetCurrentThread( ),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
TRUE,
&_hToken )){
SPLASSERT( !_hToken );
if( GetLastError() == ERROR_NO_TOKEN ){
//
// This means we are not impersonating anybody.
// Get the token out of the process.
//
if( !OpenProcessToken( GetCurrentProcess( ),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&_hToken )){
SPLASSERT( !_hToken );
return;
}
} else {
SPLASSERT( !_hToken );
return;
}
}
//
// We have a valid _hToken at this point.
//
BYTE abyPrivileges[sizeof( TOKEN_PRIVILEGES ) +
(( kPrivCount - 1 ) *
sizeof( LUID_AND_ATTRIBUTES ))];
PTOKEN_PRIVILEGES pPrivilegesNew;
pPrivilegesNew = (PTOKEN_PRIVILEGES)abyPrivileges;
ZeroMemory( abyPrivileges, sizeof( abyPrivileges ));
if( !LookupPrivilegeValue( NULL,
pszPrivilegeName,
&pPrivilegesNew->Privileges[0].Luid )){
DBGMSG( DBG_WARN,
( "AcquirePrivilege.ctr: LookupPrivilegeValue failed: %d\n",
GetLastError( )));
return;
}
//
// Save previous privileges.
//
DWORD cbPrivilegesOld = kPrivilegeSizeHint;
TStatusB bStatus;
Retry:
_pPrivilegesOld = (PTOKEN_PRIVILEGES)AllocMem( cbPrivilegesOld );
if( !_pPrivilegesOld ){
return;
}
//
// Set up the privilege set we will need.
//
pPrivilegesNew->PrivilegeCount = kPrivCount;
//
// Luid set above.
//
pPrivilegesNew->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
bStatus DBGCHK = AdjustTokenPrivileges( _hToken,
FALSE,
pPrivilegesNew,
cbPrivilegesOld,
_pPrivilegesOld,
&cbPrivilegesOld );
if( !bStatus ){
FreeMem( _pPrivilegesOld );
_pPrivilegesOld = NULL;
if( GetLastError() == ERROR_INSUFFICIENT_BUFFER ){
goto Retry;
}
DBGMSG( DBG_WARN,
( "AcquirePrivilege.ctr: AdjustTokenPrivileges failed: Error %d\n",
GetLastError( )));
return;
}
//
// _pPrivilegesOld is our valid check.
//
}
TAcquirePrivilege::
~TAcquirePrivilege(
VOID
)
/*++
Routine Description:
Restore privileges and free buffer.
_hToken needs to be close if it is non-NULL. _pPrivilegeOld
is our valid check.
Arguments:
Return Value:
--*/
{
if( _pPrivilegesOld ){
TStatusB bStatus;
bStatus DBGCHK = AdjustTokenPrivileges( _hToken,
FALSE,
_pPrivilegesOld,
0,
NULL,
NULL );
FreeMem( _pPrivilegesOld );
}
if( _hToken ){
CloseHandle( _hToken );
}
}
/********************************************************************
Security.
********************************************************************/
BOOL
TPrinterSecurity::
bInitStrings(
VOID
)
{
//
// Check whether the strings have been loaded.
//
if( gbStringsLoaded == TRUE ){
return TRUE;
}
gbStringsLoaded = TRUE;
gHelpInfoPermissions.pszHelpFileName = (LPTSTR)gszWindowsHlp;
gHelpInfoAuditing.pszHelpFileName = (LPTSTR)gszWindowsHlp;
gHelpInfoTakeOwnership.pszHelpFileName = (LPTSTR)gszWindowsHlp;
gObjectTypeDescriptor.ObjectTypeName =
pszLoadString( ghInst, IDS_PRINTER );
gpDiscretionaryAccessGroup[PERMS_NOACC].PermissionTitle =
pszLoadString( ghInst, IDS_SEC_NOACCESS );
gpDiscretionaryAccessGroup[PERMS_PRINT].PermissionTitle =
pszLoadString( ghInst, IDS_SEC_PRINT );
gpDiscretionaryAccessGroup[PERMS_DOCAD].PermissionTitle =
pszLoadString( ghInst, IDS_SEC_ADMINISTERDOCUMENTS );
gpDiscretionaryAccessGroup[PERMS_ADMIN].PermissionTitle =
pszLoadString( ghInst, IDS_SEC_ADMINISTER );
gpSystemAccessGroup[PERMS_AUDIT_PRINT].PermissionTitle =
pszLoadString( ghInst, IDS_SEC_AUDIT_PRINT );
gpSystemAccessGroup[PERMS_AUDIT_ADMINISTER].PermissionTitle =
pszLoadString( ghInst, IDS_SEC_AUDIT_ADMINISTER );
gpSystemAccessGroup[PERMS_AUDIT_DELETE].PermissionTitle =
pszLoadString( ghInst, IDS_SEC_AUDIT_DELETE );
gpSystemAccessGroup[PERMS_AUDIT_CHANGE_PERMISSIONS].PermissionTitle =
pszLoadString( ghInst, IDS_SEC_CHANGE_PERMISSIONS );
gpSystemAccessGroup[PERMS_AUDIT_TAKE_OWNERSHIP].PermissionTitle =
pszLoadString( ghInst, IDS_SEC_TAKE_OWNERSHIP );
return TRUE;
}
BOOL
TPrinterSecurity::
bHandleMessage(
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
switch( uMsg ){
case WM_INITDIALOG:
if( !bInitStrings( )){
DBGMSG( DBG_ERROR,
( "PrinterSecurity.bHandlMessage: InitStrings failed %d\n",
GetLastError( )));
}
return TRUE;
case WM_HELP:
case WM_CONTEXTMENU:
return PrintUIHelp( uMsg, _hDlg, wParam, lParam );
case WM_DESTROY:
return TRUE;
case WM_COMMAND:
switch( GET_WM_COMMAND_ID( wParam, lParam )){
case IDC_SEC_PERMS:
vCallDiscretionaryAclEditor();
break;
case IDC_SEC_AUDIT:
vCallSystemAclEditor();
break;
case IDC_SEC_OWNER:
vCallTakeOwnershipDialog();
break;
}
}
return FALSE;
}
/********************************************************************
Load the dll.
********************************************************************/
BOOL
TPrinterSecurity::
bLoadAcledit(
VOID
)
/*++
Routine Description:
Loads acledit and sets pfns.
Note: Not multithread safe, no unloading done.
Arguments:
Return Value:
TRUE = success, FALSE = error.
--*/
{
if( ghLibraryAcledit ){
return TRUE;
}
ghLibraryAcledit = LoadLibrary( gpszAclEdit );
if( !ghLibraryAcledit ){
goto Fail;
}
gpfnSedDiscretionaryAclEditor =
(PFNSED_DISCRETIONARY_ACL_EDITOR)GetProcAddress(
ghLibraryAcledit,
gpszSedDiscretionaryAclEditor );
gpfnSedSystemAclEditor =
(PFNSED_SYSTEM_ACL_EDITOR)GetProcAddress(
ghLibraryAcledit,
gpszSedSystemAclEditor );
gpfnSedTakeOwnership =
(PFNSED_TAKE_OWNERSHIP)GetProcAddress(
ghLibraryAcledit,
gpszSedTakeOwnership );
if( !gpfnSedDiscretionaryAclEditor ||
!gpfnSedSystemAclEditor ||
!gpfnSedTakeOwnership ){
FreeLibrary( ghLibraryAcledit );
ghLibraryAcledit = NULL;
goto Fail;
}
return TRUE;
Fail:
vShowUnexpectedError( NULL, IDS_ERR_PRINTER_PROP_TITLE );
return FALSE;
}
/********************************************************************
Bring up each of the dialogs.
********************************************************************/
VOID
TPrinterSecurity::
vCallDiscretionaryAclEditor(
VOID
)
/*++
Routine Description:
Edit access privileges of print queue.
Arguments:
Return Values:
--*/
{
HANDLE hPrinterWriteDac = NULL;;
DWORD dwAccess = WRITE_DAC;
SED_APPLICATION_ACCESSES ApplicationAccesses;
DWORD SedStatus;
TStatusB bStatus;
TStatus Status;
Status DBGNOCHK = 0;
PPRINTER_INFO_3 pInfo3 = NULL;
DWORD cbInfo3 = 0;
if( !bLoadAcledit( )){
goto Fail;
}
//
// Get the security descriptor.
//
if( !_pPrinterData->hPrinter( )){
Status DBGCHK = ERROR_ACCESS_DENIED;
goto Fail;
}
bStatus DBGCHK = VDataRefresh::bGetPrinter( _pPrinterData->hPrinter(),
3,
(PVOID*)&pInfo3,
&cbInfo3 );
if( !bStatus ){
SPLASSERT( !pInfo3 );
Status DBGCHK = GetLastError();
goto Fail;
}
SECURITY_CONTEXT SecurityContext;
Status DBGCHK = TPrinter::sOpenPrinter( _pPrinterData->strPrinterName(),
&dwAccess,
&hPrinterWriteDac );
if( Status == ERROR_SUCCESS){
SPLASSERT( hPrinterWriteDac );
SecurityContext.hPrinter = hPrinterWriteDac;
} else {
SPLASSERT( !hPrinterWriteDac );
SecurityContext.hPrinter = _pPrinterData->hPrinter();
}
SecurityContext.SecurityInformation = DACL_SECURITY_INFORMATION;
SecurityContext.pPrinterSecurity = this;
//
// Pass all the permissions to the ACL editor,
// and set up the type required:
//
ApplicationAccesses.Count = PERMS_COUNT;
ApplicationAccesses.AccessGroup = gpDiscretionaryAccessGroup;
ApplicationAccesses.DefaultPermName =
gpDiscretionaryAccessGroup[PERMS_PRINT].PermissionTitle;
COUNT i;
for( i = 0; i < PERMS_COUNT; ++i ){
ApplicationAccesses.AccessGroup[i].Type =
SED_DESC_TYPE_CONT_AND_NEW_OBJECT;
}
SED_OBJECT_TYPE_DESCRIPTOR Descriptor = gObjectTypeDescriptor;
Descriptor.AllowNewObjectPerms = TRUE;
Descriptor.HelpInfo = &gHelpInfoPermissions;
Status DBGCHK = (*gpfnSedDiscretionaryAclEditor)(
_hDlg,
ghInst,
(LPTSTR)(LPCTSTR)_pPrinterData->strServerName(),
&Descriptor,
&ApplicationAccesses,
(LPTSTR)(LPCTSTR)_pPrinterData->strPrinterName(),
SedCallback2,
(DWORD)&SecurityContext,
pInfo3->pSecurityDescriptor,
FALSE,
(BOOLEAN)!hPrinterWriteDac,
&SedStatus,
0 );
Fail:
if( Status ){
SetLastError( Status );
vShowUnexpectedError( NULL, IDS_ERR_PRINTER_PROP_TITLE );
}
//
// Close the printer use to write the Dac.
//
if( hPrinterWriteDac ){
ClosePrinter( hPrinterWriteDac );
}
FreeMem( pInfo3 );
}
VOID
TPrinterSecurity::
vCallSystemAclEditor(
VOID
)
/*++
Routine Description:
Edit auditing properties of print queue.
Arguments:
Return Values:
--*/
{
HANDLE hPrinterSystemAccess = NULL;
SED_APPLICATION_ACCESSES ApplicationAccesses;
DWORD SedStatus;
TStatusB bStatus;
TStatus Status;
Status DBGNOCHK = 0;
if( !bLoadAcledit( )){
return;
}
{
TAcquirePrivilege AcquirePrivilege( SE_SECURITY_NAME );
if( !VALID_OBJ( AcquirePrivilege )){
vShowUnexpectedError( NULL, IDS_ERR_PRINTER_PROP_TITLE );
return;
}
DWORD dwAccess = ACCESS_SYSTEM_SECURITY;
Status DBGCHK = TPrinter::sOpenPrinter(
_pPrinterData->strPrinterName(),
&dwAccess,
&hPrinterSystemAccess );
if( Status != ERROR_SUCCESS ){
vShowUnexpectedError( NULL, IDS_ERR_PRINTER_PROP_TITLE );
return;
}
}
//
// Get the security descriptor.
//
PPRINTER_INFO_3 pInfo3 = NULL;
DWORD cbInfo3 = 0;
bStatus DBGCHK = VDataRefresh::bGetPrinter( hPrinterSystemAccess,
3,
(PVOID*)&pInfo3,
&cbInfo3 );
if( !bStatus ){
Status DBGCHK = GetLastError();
goto Fail;
}
SECURITY_CONTEXT SecurityContext;
SecurityContext.SecurityInformation = SACL_SECURITY_INFORMATION;
SecurityContext.pPrinterSecurity = this;
SPLASSERT( hPrinterSystemAccess );
SecurityContext.hPrinter = hPrinterSystemAccess;
//
// Pass only the Print and Administer permissions to the ACL editor,
// and set up the type required:
//
ApplicationAccesses.Count = PERMS_AUDIT_COUNT;
ApplicationAccesses.AccessGroup = gpSystemAccessGroup;
ApplicationAccesses.DefaultPermName =
gpDiscretionaryAccessGroup[PERMS_PRINT].PermissionTitle;
SED_OBJECT_TYPE_DESCRIPTOR Descriptor = gObjectTypeDescriptor;
Descriptor.AllowNewObjectPerms = FALSE;
Descriptor.HelpInfo = &gHelpInfoAuditing;
Status DBGCHK = (*gpfnSedSystemAclEditor)(
_hDlg,
ghInst,
(LPTSTR)(LPCTSTR)_pPrinterData->strServerName(),
&Descriptor,
&ApplicationAccesses,
(LPTSTR)(LPCTSTR)_pPrinterData->strPrinterName(),
SedCallback2,
(DWORD)&SecurityContext,
pInfo3->pSecurityDescriptor,
FALSE,
&SedStatus,
0 );
Fail:
if( Status ){
SetLastError( Status );
vShowUnexpectedError( NULL, IDS_ERR_PRINTER_PROP_TITLE );
}
FreeMem( pInfo3 );
if( hPrinterSystemAccess ){
ClosePrinter( hPrinterSystemAccess );
}
}
VOID
TPrinterSecurity::
vCallTakeOwnershipDialog(
VOID
)
/*++
Routine Description:
Edit ownership of print queue.
How does a user get to this dialog if they can't get properties
on a printer?
Arguments:
Return Values:
--*/
{
SED_APPLICATION_ACCESSES ApplicationAccesses;
DWORD SedStatus;
TStatusB bStatus;
TStatus Status;
HANDLE hPrinterWriteOwner = NULL;
Status DBGNOCHK = 0;
if( !bLoadAcledit( )){
return;
}
//
// Get the security descriptor.
//
PPRINTER_INFO_3 pInfo3 = NULL;
DWORD cbInfo3 = 0;
//
// Attempt to retrieve the previous owner.
//
if( _pPrinterData->hPrinter( )){
bStatus DBGCHK = VDataRefresh::bGetPrinter( _pPrinterData->hPrinter(),
3,
(PVOID*)&pInfo3,
&cbInfo3 );
}
{
TAcquirePrivilege AcquirePrivilege( SE_TAKE_OWNERSHIP_NAME );
SECURITY_CONTEXT SecurityContext;
DWORD dwAccess = WRITE_OWNER;
Status DBGCHK = TPrinter::sOpenPrinter( _pPrinterData->strPrinterName(),
&dwAccess,
&hPrinterWriteOwner );
if( Status == ERROR_SUCCESS){
SPLASSERT( hPrinterWriteOwner );
SecurityContext.hPrinter = hPrinterWriteOwner;
} else {
SPLASSERT( !hPrinterWriteOwner );
SecurityContext.hPrinter = _pPrinterData->hPrinter();
}
SecurityContext.SecurityInformation = OWNER_SECURITY_INFORMATION;
SecurityContext.pPrinterSecurity = this;
ApplicationAccesses.Count = PERMS_COUNT;
ApplicationAccesses.AccessGroup = gpDiscretionaryAccessGroup;
ApplicationAccesses.DefaultPermName =
gpDiscretionaryAccessGroup[PERMS_PRINT].PermissionTitle;
COUNT i;
for( i = 0; i < PERMS_COUNT; ++i ){
ApplicationAccesses.AccessGroup[i].Type = SED_DESC_TYPE_AUDIT;
}
BOOL bCantReadOwner;
PSECURITY_DESCRIPTOR pSecurityDescriptor;
bCantReadOwner = pInfo3 ? FALSE : TRUE;
pSecurityDescriptor = pInfo3 ?
pInfo3->pSecurityDescriptor :
NULL;
TString strPrinter;
bStatus DBGCHK = strPrinter.bLoadString( ghInst, IDS_PRINTER );
Status DBGCHK = (*gpfnSedTakeOwnership)(
_hDlg,
ghInst,
(LPTSTR)(LPCTSTR)_pPrinterData->strServerName(),
(LPTSTR)(LPCTSTR)strPrinter,
(LPTSTR)(LPCTSTR)_pPrinterData->strPrinterName(),
1,
SedCallback2,
(DWORD)&SecurityContext,
pSecurityDescriptor,
(BOOLEAN)bCantReadOwner,
(BOOLEAN)!hPrinterWriteOwner,
&SedStatus,
&gHelpInfoTakeOwnership,
0 );
}
if( hPrinterWriteOwner ){
ClosePrinter( hPrinterWriteOwner );
}
FreeMem( pInfo3 );
}
/********************************************************************
Security callback routine.
********************************************************************/
DWORD
TPrinterSecurity::
SedCallback2(
HWND hwndParent,
HANDLE hInstance,
DWORD dwCallBackContext,
PSECURITY_DESCRIPTOR psdUpdated,
PSECURITY_DESCRIPTOR pSecDescNewObjects,
BOOLEAN bApplyToSubContainers,
BOOLEAN bApplyToSubObjects,
LPDWORD pdwStatusReturn
)
/*++
Routine Description:
Called by acledit to process writes.
Arguments:
<insert>.
Return Values:
<insert>.
--*/
{
UNREFERENCED_PARAMETER( pdwStatusReturn );
UNREFERENCED_PARAMETER( bApplyToSubObjects );
UNREFERENCED_PARAMETER( bApplyToSubContainers );
UNREFERENCED_PARAMETER( pSecDescNewObjects );
UNREFERENCED_PARAMETER( hInstance );
UNREFERENCED_PARAMETER( hwndParent );
PSECURITY_CONTEXT pSecurityContext;
SECURITY_DESCRIPTOR SecurityDescriptorNew;
PSECURITY_DESCRIPTOR pSelfRelativeSD = NULL;
DWORD cbSelfRelativeSD;
TStatusB bStatus;
pSecurityContext = (PSECURITY_CONTEXT)dwCallBackContext;
SPLASSERT( pSecurityContext->hPrinter );
if( InitializeSecurityDescriptor( &SecurityDescriptorNew,
SECURITY_DESCRIPTOR_REVISION1 ) &&
BuildNewSecurityDescriptor( &SecurityDescriptorNew,
pSecurityContext->SecurityInformation,
psdUpdated )){
pSelfRelativeSD = AllocCopySecurityDescriptor( &SecurityDescriptorNew,
&cbSelfRelativeSD );
} else {
DBGMSG( DBG_ERROR, ( "PrinterSecurity.SedCallback2: InitializeSD failedt %d\n",
GetLastError( )));
}
if( !pSelfRelativeSD ){
DBGMSG( DBG_WARN,
( "PrinterSecurity.SedCallback2: Alloc copy sd failed %d\n",
GetLastError( )));
SPLASSERT( GetLastError( ));
vShowUnexpectedError( NULL, IDS_ERR_PRINTER_PROP_TITLE );
return GetLastError();
}
PRINTER_INFO_3 PrinterInfo3;
PrinterInfo3.pSecurityDescriptor = pSelfRelativeSD;
bStatus DBGCHK = SetPrinter( pSecurityContext->hPrinter,
3,
(PBYTE)&PrinterInfo3,
0 );
//
// Free the newly created sd.
//
FreeMem( pSelfRelativeSD );
if( !bStatus ){
SPLASSERT( GetLastError( ));
iMessage( NULL,
IDS_ERR_PRINTER_PROP_TITLE,
IDS_ERR_SAVE_PRINTER,
MB_OK|MB_ICONHAND,
kMsgGetLastError,
NULL );
return GetLastError();
}
//
// Refresh the property page set.
//
pSecurityContext->pPrinterSecurity->vReloadPages();
return ERROR_SUCCESS;
}
/********************************************************************
Helpers.
********************************************************************/
BOOL
TPrinterSecurity::
BuildNewSecurityDescriptor(
PSECURITY_DESCRIPTOR psdNew,
SECURITY_INFORMATION SecurityInformation,
PSECURITY_DESCRIPTOR psdUpdated
)
/*++
Routine Description:
Builds new security desriptor.
Arguments:
Return Values:
--*/
{
BOOL bDefaulted = FALSE;
PSID pOwnerSid = NULL;
PSID pGroupSid = NULL;
BOOL bDaclPresent = FALSE;
PACL pDacl = NULL;
BOOL bSaclPresent = FALSE;
PACL pSacl = NULL;
TStatusB bStatus;
switch( SecurityInformation ){
case OWNER_SECURITY_INFORMATION:
if( GetSecurityDescriptorOwner( psdUpdated,
&pOwnerSid,
&bDefaulted )){
bStatus DBGCHK = SetSecurityDescriptorOwner( psdNew,
pOwnerSid,
bDefaulted );
}
break;
case DACL_SECURITY_INFORMATION:
if( GetSecurityDescriptorDacl( psdUpdated,
&bDaclPresent,
&pDacl,
&bDefaulted )) {
bStatus DBGCHK = SetSecurityDescriptorDacl( psdNew,
bDaclPresent,
pDacl,
bDefaulted );
}
break;
case SACL_SECURITY_INFORMATION:
if( GetSecurityDescriptorSacl( psdUpdated,
&bSaclPresent,
&pSacl,
&bDefaulted )) {
bStatus DBGCHK = SetSecurityDescriptorSacl( psdNew,
bSaclPresent,
pSacl,
bDefaulted );
}
break;
default:
DBGMSG( DBG_ERROR, ( "PrinterSecurity.BuildSD: Unknown type %d\n",
SecurityInformation ));
return FALSE;
}
return bStatus;
}
PSECURITY_DESCRIPTOR
TPrinterSecurity::
AllocCopySecurityDescriptor(
IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
OUT PDWORD pdwLength
)
/*++
Routine Description:
Alloc copy of security descriptor.
Arguments:
pSecurityDescriptor - sd to copy.
pdwLength - Output length.
Return Value:
Newly allocated sd. NULL if failed.
--*/
{
PSECURITY_DESCRIPTOR psdCopy;
DWORD dwLength;
dwLength = GetSecurityDescriptorLength(pSecurityDescriptor);
psdCopy = AllocMem( dwLength );
if( psdCopy ){
MakeSelfRelativeSD( pSecurityDescriptor,
psdCopy,
&dwLength);
*pdwLength = dwLength;
}
return psdCopy;
}
#endif // def SECURITY